commit 4060cb36690d7c67087aa5aff4e69c52c0ea5a33
parent c221b53171a3603e48551f1c8f644e3020b69398
Author: Matt Demanett <matt@demanett.net>
Date: Sat, 10 Aug 2019 20:15:43 -0400
S&H: Add context-menu controls to set the noise type and voltage range for the normaled inputs. #65
Diffstat:
2 files changed, 126 insertions(+), 3 deletions(-)
diff --git a/src/SampleHold.cpp b/src/SampleHold.cpp
@@ -1,6 +1,10 @@
#include "SampleHold.hpp"
+#define NOISE_TYPE "noise_type"
+#define RANGE_OFFSET "range_offset"
+#define RANGE_SCALE "range_scale"
+
void SampleHold::onReset() {
_trigger1.reset();
_value1 = 0.0f;
@@ -8,6 +12,31 @@ void SampleHold::onReset() {
_value2 = 0.0f;
}
+json_t* SampleHold::dataToJson() {
+ json_t* root = json_object();
+ json_object_set_new(root, NOISE_TYPE, json_integer((int)_noiseType));
+ json_object_set_new(root, RANGE_OFFSET, json_real(_rangeOffset));
+ json_object_set_new(root, RANGE_SCALE, json_real(_rangeScale));
+ return root;
+}
+
+void SampleHold::dataFromJson(json_t* root) {
+ json_t* nt = json_object_get(root, NOISE_TYPE);
+ if (nt) {
+ _noiseType = (NoiseType)json_integer_value(nt);
+ }
+
+ json_t* ro = json_object_get(root, RANGE_OFFSET);
+ if (ro) {
+ _rangeOffset = json_real_value(ro);
+ }
+
+ json_t* rs = json_object_get(root, RANGE_SCALE);
+ if (rs) {
+ _rangeScale = json_real_value(rs);
+ }
+}
+
void SampleHold::process(const ProcessArgs& args) {
{
lights[TRACK1_LIGHT].value = params[TRACK1_PARAM].getValue();
@@ -17,7 +46,7 @@ void SampleHold::process(const ProcessArgs& args) {
_value1 = inputs[IN1_INPUT].getVoltage();
}
else {
- _value1 = fabsf(_noise.next()) * 10.0;
+ _value1 = (noise() + _rangeOffset) * _rangeScale;
}
}
outputs[OUT1_OUTPUT].setVoltage(_value1);
@@ -31,13 +60,30 @@ void SampleHold::process(const ProcessArgs& args) {
_value2 = inputs[IN2_INPUT].getVoltage();
}
else {
- _value2 = fabsf(_noise.next()) * 10.0;
+ _value2 = (noise() + _rangeOffset) * _rangeScale;
}
}
outputs[OUT2_OUTPUT].setVoltage(_value2);
}
}
+float SampleHold::noise() {
+ switch (_noiseType) {
+ case BLUE_NOISE_TYPE: {
+ return clamp(2.0f * _blue.next(), -1.0f, 1.0f);
+ }
+ case PINK_NOISE_TYPE: {
+ return clamp(1.5f * _pink.next(), -1.0f, 1.0f);
+ }
+ case RED_NOISE_TYPE: {
+ return clamp(2.0f * _red.next(), -1.0f, 1.0f);
+ }
+ default: {
+ return clamp(_white.next(), -1.0f, 1.0f);
+ }
+ }
+}
+
struct SampleHoldWidget : ModuleWidget {
static constexpr int hp = 3;
@@ -89,6 +135,67 @@ struct SampleHoldWidget : ModuleWidget {
addChild(createLight<SmallLight<GreenLight>>(track1LightPosition, module, SampleHold::TRACK1_LIGHT));
addChild(createLight<SmallLight<GreenLight>>(track2LightPosition, module, SampleHold::TRACK2_LIGHT));
}
+
+ struct NoiseTypeMenuItem : MenuItem {
+ SampleHold* _module;
+ SampleHold::NoiseType _noiseType;
+
+ NoiseTypeMenuItem(SampleHold* module, const char* label, SampleHold::NoiseType noiseType)
+ : _module(module)
+ , _noiseType(noiseType)
+ {
+ this->text = label;
+ }
+
+ void onAction(const event::Action& e) override {
+ _module->_noiseType = _noiseType;
+ }
+
+ void step() override {
+ rightText = _module->_noiseType == _noiseType ? "✔" : "";
+ }
+ };
+
+ struct RangeMenuItem : MenuItem {
+ SampleHold* _module;
+ float _offset, _scale;
+
+ RangeMenuItem(SampleHold* module, const char* label, float offset, float scale)
+ : _module(module)
+ , _offset(offset)
+ , _scale(scale)
+ {
+ this->text = label;
+ }
+
+ void onAction(const event::Action& e) override {
+ _module->_rangeOffset = _offset;
+ _module->_rangeScale = _scale;
+ }
+
+ void step() override {
+ rightText = (_module->_rangeOffset == _offset && _module->_rangeScale == _scale) ? "✔" : "";
+ }
+ };
+
+ void appendContextMenu(Menu* menu) override {
+ SampleHold* m = dynamic_cast<SampleHold*>(module);
+ assert(m);
+ menu->addChild(new MenuLabel());
+ menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: blue", SampleHold::BLUE_NOISE_TYPE));
+ menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: white", SampleHold::WHITE_NOISE_TYPE));
+ menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: pink", SampleHold::PINK_NOISE_TYPE));
+ menu->addChild(new NoiseTypeMenuItem(m, "Normal noise: red", SampleHold::RED_NOISE_TYPE));
+ menu->addChild(new MenuLabel());
+ menu->addChild(new RangeMenuItem(m, "Normal range: +/-10V", 0.0f, 10.0f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: +/-5V", 0.0f, 5.0f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: +/-3V", 0.0f, 3.0f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: +/-1V", 0.0f, 1.0f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: 0V-10V", 1.0f, 5.0f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: 0V-5V", 1.0f, 2.5f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: 0V-3V", 1.0f, 1.5f));
+ menu->addChild(new RangeMenuItem(m, "Normal range: 0V-1V", 1.0f, 0.5f));
+ }
};
Model* modelSampleHold = bogaudio::createModel<SampleHold, SampleHoldWidget>("Bogaudio-SampleHold", "S&H", "dual sample (or track) and hold", "Sample and hold", "Dual");
diff --git a/src/SampleHold.hpp b/src/SampleHold.hpp
@@ -38,9 +38,22 @@ struct SampleHold : Module {
NUM_LIGHTS
};
+ enum NoiseType {
+ WHITE_NOISE_TYPE,
+ BLUE_NOISE_TYPE,
+ PINK_NOISE_TYPE,
+ RED_NOISE_TYPE
+ };
+
Trigger _trigger1, _trigger2;
float _value1, _value2;
- WhiteNoiseGenerator _noise;
+ BlueNoiseGenerator _blue;
+ WhiteNoiseGenerator _white;
+ PinkNoiseGenerator _pink;
+ RedNoiseGenerator _red;
+ NoiseType _noiseType = WHITE_NOISE_TYPE;
+ float _rangeOffset = 1.0f;
+ float _rangeScale = 5.0f;
SampleHold()
: _value1(0.0f)
@@ -56,7 +69,10 @@ struct SampleHold : Module {
}
void onReset() override;
+ json_t* dataToJson() override;
+ void dataFromJson(json_t* root) override;
void process(const ProcessArgs& args) override;
+ float noise();
};
} // namespace bogaudio