
#include "XFade.hpp"

void XFade::sampleRateChange() {
	for (int c = 0; c < maxChannels; ++c) {
		_mixSL[c].setParams(APP->engine->getSampleRate(), 10.0f, 2.0f);
	}
}

bool XFade::active() {
	return outputs[OUT_OUTPUT].isConnected();
}

int XFade::channels() {
	return inputs[A_INPUT].getChannels();
}

void XFade::processChannel(const ProcessArgs& args, int c) {
	bool linear = params[LINEAR_PARAM].getValue() > 0.5f;

	float mix = params[MIX_PARAM].getValue();
	if (inputs[MIX_INPUT].isConnected()) {
		mix *= clamp(inputs[MIX_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f);
	}
	mix = _mixSL[c].next(mix);

	float curveIn = params[CURVE_PARAM].getValue();

	if (_linear != linear || _mix[c] != mix || _curveIn[c] != curveIn) {
		_linear = linear;
		_mix[c] = mix;
		_curveIn[c] = curveIn;
		if (!linear) {
			curveIn = powf(params[CURVE_PARAM].getValue(), 0.082f);
		}
		curveIn *= 2.0f;
		curveIn -= 1.0f;

		_mixer[c].setParams(mix, curveIn, linear);
	}

	outputs[OUT_OUTPUT].setChannels(_channels);
	outputs[OUT_OUTPUT].setVoltage(_mixer[c].next(inputs[A_INPUT].getVoltage(c), inputs[B_INPUT].getVoltage(c)), c);
}

struct XFadeWidget : BGModuleWidget {
	static constexpr int hp = 3;

	XFadeWidget(XFade* module) {
		setModule(module);
		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
		setPanel(box.size, "XFade");
		createScrews();

		// generated by svg_widgets.rb
		auto mixParamPosition = Vec(8.0, 36.0);
		auto curveParamPosition = Vec(14.5, 152.5);
		auto linearParamPosition = Vec(25.5, 177.0);

		auto mixInputPosition = Vec(10.5, 77.0);
		auto aInputPosition = Vec(10.5, 213.0);
		auto bInputPosition = Vec(10.5, 248.0);

		auto outOutputPosition = Vec(10.5, 286.0);
		// end generated by svg_widgets.rb

		addParam(createParam<Knob29>(mixParamPosition, module, XFade::MIX_PARAM));
		{
			auto w = createParam<Knob16>(curveParamPosition, module, XFade::CURVE_PARAM);
			auto k = dynamic_cast<SvgKnob*>(w);
			k->minAngle = -0.5 * M_PI;
			k->maxAngle = 0.5 * M_PI;
			addParam(w);
		}
		addParam(createParam<IndicatorButtonGreen9>(linearParamPosition, module, XFade::LINEAR_PARAM));

		addInput(createInput<Port24>(mixInputPosition, module, XFade::MIX_INPUT));
		addInput(createInput<Port24>(aInputPosition, module, XFade::A_INPUT));
		addInput(createInput<Port24>(bInputPosition, module, XFade::B_INPUT));

		addOutput(createOutput<Port24>(outOutputPosition, module, XFade::OUT_OUTPUT));
	}
};

Model* modelXFade = bogaudio::createModel<XFade, XFadeWidget>("Bogaudio-XFade", "XFADE", "Crossfader", "Mixer", "Polyphonic");
