[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/node-3d/webaudio/master/src/cpp/audio-node.cpp [Back]  [Original]

#include "audio-node.hpp"
#include "audio-context.hpp"
#include "audio-param.hpp"


IMPLEMENT_ES5_CLASS(AudioNode);

void AudioNode::init(Napi::Env env, Napi::Object exports) {
	Napi::Function ctor = wrap(env);
	JS_ASSIGN_SETTER(channelInterpretation);
	JS_ASSIGN_SETTER(channelCountMode);
	JS_ASSIGN_SETTER(channelCount);
	JS_ASSIGN_METHOD(disconnect);
	JS_ASSIGN_METHOD(connect);
	JS_ASSIGN_GETTER(numberOfOutputs);
	JS_ASSIGN_GETTER(numberOfInputs);
	JS_ASSIGN_GETTER(context);
	JS_ASSIGN_METHOD(destroy);
	JS_ASSIGN_METHOD(diagnose);

	exports.Set("AudioNode", ctor);
}


bool AudioNode::isAudioNode(Napi::Object obj) {
	return obj.InstanceOf(_ctorEs5.Value());
}


inline std::string fromChannelCountMode(lab::ChannelCountMode mode) {
	if (mode == lab::ChannelCountMode::ClampedMax) {
		return "clamped-max";
	} else if (mode == lab::ChannelCountMode::Explicit) {
		return "explicit";
	} else {
		return "max";
	}
}


inline lab::ChannelCountMode toChannelCountMode(const std::string &mode) {
	if (mode == "clamped-max") {
		return lab::ChannelCountMode::ClampedMax;
	} else if (mode == "explicit") {
		return lab::ChannelCountMode::Explicit;
	} else {
		return lab::ChannelCountMode::Max;
	}
}


inline std::string fromChannelInterpretation(lab::ChannelInterpretation io) {
	if (io == lab::ChannelInterpretation::Discrete) {
		return "discrete";
	} else {
		return "speakers";
	}
}


inline lab::ChannelInterpretation toChannelInterpretation(const std::string &io) {
	if (io == "discrete") {
		return lab::ChannelInterpretation::Discrete;
	} else {
		return lab::ChannelInterpretation::Speakers;
	}
}


AudioNode::AudioNode(const Napi::CallbackInfo &info) : CommonNode(info.This(), "AudioNode") {
	NAPI_ENV;
	super(info);

	Napi::Object context = info[0].As();
	Napi::External extNode = info[1].As();

	NodePtr *ext = reinterpret_cast(extNode.Data());

	reset(context, *ext);

	_channelCountMode = fromChannelCountMode(_impl->channelCountMode());
	_channelInterpretation = fromChannelInterpretation(_impl->channelInterpretation());
}


AudioNode::~AudioNode() {
	_destroy();
}


void AudioNode::_destroy() {
	DES_CHECK;
	CommonNode::_destroy();
}


// node2 node1.connect(node2);
// node2 node1.connect(node2, output);
// node2 node1.connect(node2, output, input);
// undefined node1.connect(param);
// undefined node1.connect(param, output);
JS_IMPLEMENT_METHOD(AudioNode, connect) {
	THIS_CHECK;
	REQ_OBJ_ARG(0, destination);

	Napi::Object context = _context.Value();
	AudioContext *audioContext = AudioContext::unwrap(context);

	lab::AudioContext *ctx = audioContext->getCtx().get();

	if (isAudioNode(destination)) {
		LET_INT32_ARG(1, output);
		LET_INT32_ARG(2, input);

		AudioNode *destNode = AudioNode::unwrap(destination);

		ctx->connect(destNode->_impl, _impl, input, output);
		if (destNode->_impl.get() == static_cast(ctx->destinationNode().get())) {
			ctx->synchronizeConnections();
		}
	} else if (AudioParam::isAudioParam(destination)) {
		LET_INT32_ARG(1, output);

		AudioParam *destParam = AudioParam::unwrap(destination);

		ctx->connectParam(destParam->getParam(), _impl, output);
	}

	RET_UNDEFINED;
}


// undefined node1.disconnect();
// undefined node1.disconnect(dest);
// undefined node1.disconnect(dest, output);
// undefined node1.disconnect(dest, output, input);
// MAP TO --->
// ctx->disconnect(NodePtr destination, NodePtr source, int input, int output)
// ctx->disconnect(NodePtr source, int output)
JS_IMPLEMENT_METHOD(AudioNode, disconnect) {
	THIS_CHECK;
	int output = 0;
	int input = 0;
	Napi::Object destination;

	Napi::Object context = _context.Value();
	AudioContext *audioContext = AudioContext::unwrap(context);
	lab::AudioContext *ctx = audioContext->getCtx().get();

	if (info.Length() == 1) {
		if (info[0].IsObject()) {
			REQ_OBJ_ARG(0, destArg);
			destination = destArg;
		} else if (info[0].IsNumber()) {
			REQ_INT_ARG(0, outputArg);
			output = outputArg;
		}
	} else if (info.Length() == 2) {
		REQ_OBJ_ARG(0, destArg);
		REQ_INT_ARG(1, outputArg);

		destination = destArg;
		output = outputArg;
	} else if (info.Length() == 3) {
		REQ_OBJ_ARG(0, destArg);
		REQ_INT_ARG(1, outputArg);
		REQ_INT_ARG(2, inputArg);

		destination = destArg;
		output = outputArg;
		input = inputArg;
	} else {
		// Disconnect self
		ctx->disconnect(_impl, output);
		RET_UNDEFINED;
	}

	if (AudioNode::isAudioNode(destination)) {
		AudioNode *destNode = AudioNode::unwrap(destination);
		ctx->disconnect(destNode->_impl, _impl, input, output);
	} else if (AudioParam::isAudioParam(destination)) {
		AudioParam *destParam = AudioParam::unwrap(destination);
		ParamPtr param = destParam->getParam();
		ctx->disconnectParam(param, _impl, output);
	}

	RET_UNDEFINED;
}


JS_IMPLEMENT_GETTER(AudioNode, context) {
	THIS_CHECK;
	RET_VALUE(_context.Value());
}


JS_IMPLEMENT_GETTER(AudioNode, numberOfInputs) {
	THIS_CHECK;
	RET_NUM(static_cast(_impl->numberOfInputs()));
}


JS_IMPLEMENT_GETTER(AudioNode, numberOfOutputs) {
	THIS_CHECK;
	RET_NUM(static_cast(_impl->numberOfOutputs()));
}


JS_IMPLEMENT_GETTER(AudioNode, channelCount) {
	THIS_CHECK;
	RET_NUM(static_cast(_impl->channelCount()));
}


JS_IMPLEMENT_SETTER(AudioNode, channelCount) {
	THIS_CHECK;
	SETTER_UINT32_ARG;
	Napi::Object context = _context.Value();
	AudioContext *audioContext = AudioContext::unwrap(context);

	lab::ContextGraphLock graphLock(audioContext->getCtx().get(), "AudioNode::channelCountSetter");
	_impl->setChannelCount(graphLock, v);

	emit("channelCount", 1, &value);
	RET_UNDEFINED;
}


JS_IMPLEMENT_GETTER(AudioNode, channelCountMode) {
	THIS_CHECK;
	RET_STR(_channelCountMode);
}

JS_IMPLEMENT_SETTER(AudioNode, channelCountMode) {
	THIS_CHECK;
	SETTER_STR_ARG;
	CACHE_CAS(_channelCountMode, v);

	// TODO: may be additional actions on change?

	emit("channelCountMode", 1, &value);
	RET_UNDEFINED;
}


JS_IMPLEMENT_GETTER(AudioNode, channelInterpretation) {
	THIS_CHECK;
	RET_STR(_channelInterpretation);
}

JS_IMPLEMENT_SETTER(AudioNode, channelInterpretation) {
	THIS_CHECK;
	SETTER_STR_ARG;
	CACHE_CAS(_channelInterpretation, v);

	// TODO: may be additional actions on change?

	emit("channelInterpretation", 1, &value);
	RET_UNDEFINED;
}


JS_IMPLEMENT_METHOD(AudioNode, destroy) {
	THIS_CHECK;
	emit("destroy");
	_destroy();
	RET_UNDEFINED;
}

JS_IMPLEMENT_METHOD(AudioNode, diagnose) {
	THIS_CHECK;
	Napi::Object context = _context.Value();
	AudioContext *audioContext = AudioContext::unwrap(context);

	lab::AudioContext *ctx = audioContext->getCtx().get();
	ctx->diagnose(_impl);
	RET_UNDEFINED;
}

Web Proxy Viewer  |  New URL  |  Original Page