| @@ -1,13 +1,12 @@ | |||
| #include <string> | |||
| #include <chrono> | |||
| #include "plugin.hpp" | |||
| #include "dsp/digital.hpp" | |||
| #include "dsp/samplerate.hpp" | |||
| #include "dsp/ringbuffer.hpp" | |||
| //#include "dsp/digital.hpp" | |||
| //#include "dsp/samplerate.hpp" | |||
| //#include "dsp/ringbuffer.hpp" | |||
| #include "peaks/processors.h" | |||
| #include "AudibleInstruments.hpp" | |||
| //#include "AudibleInstruments.hpp" | |||
| enum SwitchIndex { | |||
| @@ -109,12 +108,12 @@ struct Peaks : Module { | |||
| int16_t output[kBlockSize]; | |||
| int16_t brightness[kNumChannels] = {0, 0}; | |||
| SchmittTrigger switches_[2]; | |||
| dsp::SchmittTrigger switches_[2]; | |||
| peaks::GateFlags gate_flags[2] = {0, 0}; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<2> outputSrc; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||
| bool initNumberStation = false; | |||
| @@ -134,7 +133,19 @@ struct Peaks : Module { | |||
| size_t render_block_ = kNumBlocks / 2; | |||
| Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Peaks() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(KNOB_1_PARAM, 0.0f, 65535.0f, 32678.0f, "Knob 1"); | |||
| configParam(KNOB_2_PARAM, 0.0f, 65535.0f, 32678.0f, "Knob 1"); | |||
| configParam(KNOB_3_PARAM, 0.0f, 65535.0f, 32678.0f, "Knob 1"); | |||
| configParam(KNOB_4_PARAM, 0.0f, 65535.0f, 32678.0f, "Knob 1"); | |||
| configButton(BUTTON_1_PARAM, "Mode"); | |||
| configButton(BUTTON_2_PARAM, "Mode"); | |||
| configButton(TRIG_1_PARAM, "Trigger 1"); | |||
| configButton(TRIG_2_PARAM, "Trigger 2"); | |||
| settings_.edit_mode = EDIT_MODE_TWIN; | |||
| settings_.function[0] = FUNCTION_ENVELOPE; | |||
| settings_.function[1] = FUNCTION_ENVELOPE; | |||
| @@ -184,7 +195,7 @@ struct Peaks : Module { | |||
| setFunction(1, function_[1]); | |||
| } | |||
| json_t* toJson() override { | |||
| json_t* dataToJson() override { | |||
| saveState(); | |||
| @@ -206,7 +217,7 @@ struct Peaks : Module { | |||
| return rootJ; | |||
| } | |||
| void fromJson(json_t* rootJ) override { | |||
| void dataFromJson(json_t* rootJ) override { | |||
| json_t* editModeJ = json_object_get(rootJ, "edit_mode"); | |||
| if (editModeJ) { | |||
| settings_.edit_mode = static_cast<EditMode>(json_integer_value(editModeJ)); | |||
| @@ -240,7 +251,7 @@ struct Peaks : Module { | |||
| init(); | |||
| } | |||
| void step() override { | |||
| void process(const ProcessArgs& args) override { | |||
| poll(); | |||
| pollPots(); | |||
| @@ -259,21 +270,21 @@ struct Peaks : Module { | |||
| } | |||
| uint32_t external_gate_inputs = 0; | |||
| external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); | |||
| external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0); | |||
| external_gate_inputs |= (inputs[GATE_1_INPUT].getVoltage() ? 1 : 0); | |||
| external_gate_inputs |= (inputs[GATE_2_INPUT].getVoltage() ? 2 : 0); | |||
| uint32_t buttons = 0; | |||
| buttons |= (params[TRIG_1_PARAM].value ? 1 : 0); | |||
| buttons |= (params[TRIG_2_PARAM].value ? 2 : 0); | |||
| buttons |= (params[TRIG_1_PARAM].getValue() ? 1 : 0); | |||
| buttons |= (params[TRIG_2_PARAM].getValue() ? 2 : 0); | |||
| uint32_t gate_inputs = external_gate_inputs | buttons; | |||
| // Prepare sample rate conversion. | |||
| // Peaks is sampling at 48kHZ. | |||
| outputSrc.setRates(48000, engineGetSampleRate()); | |||
| outputSrc.setRates(48000, args.sampleRate); | |||
| int inLen = kBlockSize; | |||
| int outLen = outputBuffer.capacity(); | |||
| Frame<2> f[kBlockSize]; | |||
| dsp::Frame<2> f[kBlockSize]; | |||
| // Process an entire block of data from the IOBuffer. | |||
| for (size_t k = 0; k < kBlockSize; ++k) { | |||
| @@ -301,12 +312,12 @@ struct Peaks : Module { | |||
| // Update outputs. | |||
| if (!outputBuffer.empty()) { | |||
| Frame<2> f = outputBuffer.shift(); | |||
| dsp::Frame<2> f = outputBuffer.shift(); | |||
| // Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV. | |||
| // TODO Check the output values against an actual device. | |||
| outputs[OUT_1_OUTPUT].value = rescale(static_cast<float>(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f); | |||
| outputs[OUT_2_OUTPUT].value = rescale(static_cast<float>(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f); | |||
| outputs[OUT_1_OUTPUT].setVoltage(rescale(static_cast<float>(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f)); | |||
| outputs[OUT_2_OUTPUT].setVoltage(rescale(static_cast<float>(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f)); | |||
| } | |||
| } | |||
| @@ -467,7 +478,7 @@ void Peaks::lockPots() { | |||
| void Peaks::pollPots() { | |||
| for (uint8_t i = 0; i < kNumAdcChannels; ++i) { | |||
| adc_lp_[i] = (int32_t(params[KNOB_1_PARAM + i].value) + adc_lp_[i] * 7) >> 3; | |||
| adc_lp_[i] = (int32_t(params[KNOB_1_PARAM + i].getValue()) + adc_lp_[i] * 7) >> 3; | |||
| int32_t value = adc_lp_[i]; | |||
| int32_t current_value = adc_value_[i]; | |||
| if (value >= current_value + adc_threshold_[i] || | |||
| @@ -530,7 +541,7 @@ long long Peaks::getSystemTimeMs() { | |||
| void Peaks::poll() { | |||
| for (uint8_t i = 0; i < 2; ++i) { | |||
| if (switches_[i].process(params[BUTTON_1_PARAM + i].value)) { | |||
| if (switches_[i].process(params[BUTTON_1_PARAM + i].getValue())) { | |||
| press_time_[i] = getSystemTimeMs(); | |||
| } | |||
| @@ -618,80 +629,67 @@ void Peaks::refreshLeds() { | |||
| b[1] = processors[1].number_station().gate() ? 255 : 0; | |||
| } | |||
| lights[TRIG_1_LIGHT].value = rescale(static_cast<float>(b[0]), 0.0f, 255.0f, 0.0f, 1.0f); | |||
| lights[TRIG_2_LIGHT].value = rescale(static_cast<float>(b[1]), 0.0f, 255.0f, 0.0f, 1.0f); | |||
| const float deltaTime = APP->engine->getSampleTime(); | |||
| lights[TRIG_1_LIGHT].setSmoothBrightness(rescale(static_cast<float>(b[0]), 0.0f, 255.0f, 0.0f, 1.0f), deltaTime); | |||
| lights[TRIG_2_LIGHT].setSmoothBrightness(rescale(static_cast<float>(b[1]), 0.0f, 255.0f, 0.0f, 1.0f), deltaTime); | |||
| } | |||
| struct PeaksWidget : ModuleWidget { | |||
| PeaksWidget(Peaks* module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(plugin, "res/Peaks.svg"))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 0))); | |||
| addChild(Widget::create<ScrewSilver>(Vec(15, 365))); | |||
| addParam(ParamWidget::create<TL1105>(Vec(8.5, 52), module, Peaks::BUTTON_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 74), module, Peaks::TWIN_MODE_LIGHT)); | |||
| addParam(ParamWidget::create<TL1105>(Vec(8.5, 89), module, Peaks::BUTTON_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 111), module, Peaks::FUNC_1_LIGHT)); | |||
| addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 126.75), module, Peaks::FUNC_2_LIGHT)); | |||
| addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 142.5), module, Peaks::FUNC_3_LIGHT)); | |||
| addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 158), module, Peaks::FUNC_4_LIGHT)); | |||
| addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 51), module, Peaks::KNOB_1_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||
| addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 115), module, Peaks::KNOB_2_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||
| addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 179), module, Peaks::KNOB_3_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||
| addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 244), module, Peaks::KNOB_4_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||
| addParam(ParamWidget::create<LEDBezel>(Vec(11, 188), module, Peaks::TRIG_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addParam(ParamWidget::create<LEDBezel>(Vec(11, 273), module, Peaks::TRIG_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(ModuleLightWidget::create<LEDBezelLight<GreenLight>>(Vec(11, 188).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_1_LIGHT)); | |||
| addChild(ModuleLightWidget::create<LEDBezelLight<GreenLight>>(Vec(11, 273).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_2_LIGHT)); | |||
| addInput(Port::create<PJ301MPort>(Vec(10, 230), Port::INPUT, module, Peaks::GATE_1_INPUT)); | |||
| addInput(Port::create<PJ301MPort>(Vec(10, 315), Port::INPUT, module, Peaks::GATE_2_INPUT)); | |||
| addOutput(Port::create<PJ301MPort>(Vec(53, 315), Port::OUTPUT, module, Peaks::OUT_1_OUTPUT)); | |||
| addOutput(Port::create<PJ301MPort>(Vec(86, 315), Port::OUTPUT, module, Peaks::OUT_2_OUTPUT)); | |||
| PeaksWidget(Peaks* module) { | |||
| setModule(module); | |||
| setPanel(Svg::load(asset::plugin(pluginInstance, "res/Peaks.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParam<TL1105>((Vec(8.5, 52)), module, Peaks::BUTTON_1_PARAM)); | |||
| addParam(createParam<TL1105>((Vec(8.5, 89)), module, Peaks::BUTTON_2_PARAM)); | |||
| addParam(createParamCentered<LEDBezel>(Vec(21, 200), module, Peaks::TRIG_1_PARAM)); | |||
| addParam(createParamCentered<LEDBezel>(Vec(21, 285), module, Peaks::TRIG_2_PARAM)); | |||
| addChild(createLightCentered<LEDBezelLight<GreenLight>>(Vec(21, 200), module, Peaks::TRIG_1_LIGHT)); | |||
| addChild(createLightCentered<LEDBezelLight<GreenLight>>(Vec(21, 285), module, Peaks::TRIG_2_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 74), module, Peaks::TWIN_MODE_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 111), module, Peaks::FUNC_1_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 126.75), module, Peaks::FUNC_2_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 142.5), module, Peaks::FUNC_3_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 158), module, Peaks::FUNC_4_LIGHT)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 51), module, Peaks::KNOB_1_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 115), module, Peaks::KNOB_2_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 179), module, Peaks::KNOB_3_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 244), module, Peaks::KNOB_4_PARAM)); | |||
| addInput(createInput<PJ301MPort>((Vec(10, 230)), module, Peaks::GATE_1_INPUT)); | |||
| addInput(createInput<PJ301MPort>((Vec(10, 315)), module, Peaks::GATE_2_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>((Vec(53., 315.)), module, Peaks::OUT_1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>((Vec(86., 315.)), module, Peaks::OUT_2_OUTPUT)); | |||
| } | |||
| Menu* createContextMenu() override { | |||
| Menu* menu = ModuleWidget::createContextMenu(); | |||
| Peaks* peaks = dynamic_cast<Peaks*>(this->module); | |||
| void appendContextMenu(Menu* menu) override { | |||
| struct SnapModeItem : MenuItem { | |||
| Peaks* peaks; | |||
| void onAction(EventAction& e) override { | |||
| peaks->snap_mode_ = !peaks->snap_mode_; | |||
| } | |||
| void step() override { | |||
| rightText = (peaks->snap_mode_) ? "✔" : ""; | |||
| MenuItem::step(); | |||
| } | |||
| }; | |||
| menu->addChild(new MenuSeparator); | |||
| Peaks *peaks = dynamic_cast<Peaks*>(this->module); | |||
| struct NumberStationItem : MenuItem { | |||
| Peaks* peaks; | |||
| void onAction(EventAction& e) override { | |||
| peaks->initNumberStation = true; | |||
| } | |||
| void step() override { | |||
| rightText = (peaks->processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) ? "✔" : ""; | |||
| MenuItem::step(); | |||
| } | |||
| }; | |||
| menu->addChild(construct<MenuLabel>()); | |||
| menu->addChild(construct<SnapModeItem>(&SnapModeItem::text, "Snap Mode", &SnapModeItem::peaks, peaks)); | |||
| menu->addChild(createBoolPtrMenuItem("Snap mode", "", &peaks->snap_mode_)); | |||
| menu->addChild(construct<MenuLabel>()); | |||
| menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Secret Modes")); | |||
| menu->addChild(construct<NumberStationItem>(&NumberStationItem::text, "Number Station", &NumberStationItem::peaks, peaks)); | |||
| return menu; | |||
| menu->addChild(createBoolMenuItem("Number station", "", | |||
| [=]() {return peaks->processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION;}, | |||
| [=](bool val) {peaks->initNumberStation = true;} | |||
| )); | |||
| } | |||
| }; | |||
| Model* modelPeaks = Model::create<Peaks, PeaksWidget>("Audible Instruments", "Peaks", "Percussive Synthesizer", UTILITY_TAG, LFO_TAG, DRUM_TAG); | |||
| Model* modelPeaks = createModel<Peaks, PeaksWidget>("Peaks"); | |||