You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

670 lines
20KB

  1. #include <string>
  2. #include <chrono>
  3. #include "dsp/digital.hpp"
  4. #include "dsp/samplerate.hpp"
  5. #include "dsp/ringbuffer.hpp"
  6. #include "peaks/io_buffer.h"
  7. #include "peaks/processors.h"
  8. #include "AudibleInstruments.hpp"
  9. enum SwitchIndex {
  10. SWITCH_TWIN_MODE,
  11. SWITCH_FUNCTION,
  12. SWITCH_GATE_TRIG_1,
  13. SWITCH_GATE_TRIG_2
  14. };
  15. enum EditMode {
  16. EDIT_MODE_TWIN,
  17. EDIT_MODE_SPLIT,
  18. EDIT_MODE_FIRST,
  19. EDIT_MODE_SECOND,
  20. EDIT_MODE_LAST
  21. };
  22. enum Function {
  23. FUNCTION_ENVELOPE,
  24. FUNCTION_LFO,
  25. FUNCTION_TAP_LFO,
  26. FUNCTION_DRUM_GENERATOR,
  27. FUNCTION_MINI_SEQUENCER,
  28. FUNCTION_PULSE_SHAPER,
  29. FUNCTION_PULSE_RANDOMIZER,
  30. FUNCTION_FM_DRUM_GENERATOR,
  31. FUNCTION_LAST,
  32. FUNCTION_FIRST_ALTERNATE_FUNCTION = FUNCTION_MINI_SEQUENCER
  33. };
  34. struct Settings {
  35. uint8_t edit_mode;
  36. uint8_t function[2];
  37. uint8_t pot_value[8];
  38. bool snap_mode;
  39. };
  40. static const int32_t kLongPressDuration = 600;
  41. static const uint8_t kNumAdcChannels = 4;
  42. static const uint16_t kAdcThresholdUnlocked = 1 << (16 - 10); // 10 bits
  43. static const uint16_t kAdcThresholdLocked = 1 << (16 - 8); // 8 bits
  44. // Global scope, so variables can be accessed by process() function.
  45. int16_t gOutputBuffer[peaks::kBlockSize];
  46. int16_t gBrightness[2] = {0, 0};
  47. static void set_led_brightness(int channel, int16_t value) {
  48. gBrightness[channel] = value;
  49. }
  50. // File scope because of IOBuffer function signature.
  51. // It cannot refer to a member function of class Peaks().
  52. static void process(peaks::IOBuffer::Block* block, size_t size) {
  53. for (size_t i = 0; i < peaks::kNumChannels; ++i) {
  54. // TODO
  55. // processors[i].Process(block->input[i], gOutputBuffer, size);
  56. set_led_brightness(i, gOutputBuffer[0]);
  57. for (size_t j = 0; j < size; ++j) {
  58. // From calibration_data.h, shifting signed to unsigned values.
  59. int32_t shifted_value = 32767 + static_cast<int32_t>(gOutputBuffer[j]);
  60. CONSTRAIN(shifted_value, 0, 65535);
  61. block->output[i][j] = static_cast<uint16_t>(shifted_value);
  62. }
  63. }
  64. }
  65. struct Peaks : Module {
  66. enum ParamIds {
  67. KNOB_1_PARAM,
  68. KNOB_2_PARAM,
  69. KNOB_3_PARAM,
  70. KNOB_4_PARAM,
  71. BUTTON_1_PARAM,
  72. BUTTON_2_PARAM,
  73. TRIG_1_PARAM,
  74. TRIG_2_PARAM,
  75. NUM_PARAMS
  76. };
  77. enum InputIds {
  78. GATE_1_INPUT,
  79. GATE_2_INPUT,
  80. NUM_INPUTS
  81. };
  82. enum OutputIds {
  83. OUT_1_OUTPUT,
  84. OUT_2_OUTPUT,
  85. NUM_OUTPUTS
  86. };
  87. enum LightIds {
  88. TRIG_1_LIGHT,
  89. TRIG_2_LIGHT,
  90. TWIN_MODE_LIGHT,
  91. FUNC_1_LIGHT,
  92. FUNC_2_LIGHT,
  93. FUNC_3_LIGHT,
  94. FUNC_4_LIGHT,
  95. NUM_LIGHTS
  96. };
  97. static const peaks::ProcessorFunction function_table_[FUNCTION_LAST][2];
  98. EditMode edit_mode_ = EDIT_MODE_TWIN;
  99. Function function_[2] = {FUNCTION_ENVELOPE, FUNCTION_ENVELOPE};
  100. Settings settings_;
  101. uint8_t pot_value_[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  102. bool snap_mode_ = false;
  103. bool snapped_[4] = {false, false, false, false};
  104. int32_t adc_lp_[kNumAdcChannels] = {0, 0, 0, 0};
  105. int32_t adc_value_[kNumAdcChannels] = {0, 0, 0, 0};
  106. int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0};
  107. long long press_time_[2] = {0, 0};
  108. SchmittTrigger switches_[2];
  109. peaks::IOBuffer ioBuffer;
  110. peaks::GateFlags gate_flags[2] = {0, 0};
  111. SampleRateConverter<2> outputSrc;
  112. DoubleRingBuffer<Frame<2>, 256> outputBuffer;
  113. bool initNumberStation = false;
  114. peaks::Processors processors[2];
  115. Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  116. settings_.edit_mode = EDIT_MODE_TWIN;
  117. settings_.function[0] = FUNCTION_ENVELOPE;
  118. settings_.function[1] = FUNCTION_ENVELOPE;
  119. settings_.snap_mode = false;
  120. std::fill(&settings_.pot_value[0], &settings_.pot_value[8], 0);
  121. memset(&ioBuffer, 0, sizeof(ioBuffer));
  122. memset(&processors[0], 0, sizeof(processors[0]));
  123. memset(&processors[1], 0, sizeof(processors[1]));
  124. ioBuffer.Init();
  125. processors[0].Init(0);
  126. processors[1].Init(1);
  127. }
  128. void onReset() override {
  129. init();
  130. }
  131. void init() {
  132. std::fill(&pot_value_[0], &pot_value_[8], 0);
  133. std::fill(&press_time_[0], &press_time_[1], 0);
  134. std::fill(&gBrightness[0], &gBrightness[1], 0);
  135. std::fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0);
  136. std::fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0);
  137. std::fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0);
  138. std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false);
  139. edit_mode_ = static_cast<EditMode>(settings_.edit_mode);
  140. function_[0] = static_cast<Function>(settings_.function[0]);
  141. function_[1] = static_cast<Function>(settings_.function[1]);
  142. std::copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]);
  143. if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) {
  144. lockPots();
  145. for (uint8_t i = 0; i < 4; ++i) {
  146. processors[0].set_parameter(
  147. i,
  148. static_cast<uint16_t>(pot_value_[i]) << 8);
  149. processors[1].set_parameter(
  150. i,
  151. static_cast<uint16_t>(pot_value_[i + 4]) << 8);
  152. }
  153. }
  154. snap_mode_ = settings_.snap_mode;
  155. changeControlMode();
  156. setFunction(0, function_[0]);
  157. setFunction(1, function_[1]);
  158. }
  159. json_t *toJson() override {
  160. saveState();
  161. json_t *rootJ = json_object();
  162. json_object_set_new(rootJ, "edit_mode", json_integer((int)settings_.edit_mode));
  163. json_object_set_new(rootJ, "fcn_channel_1", json_integer((int)settings_.function[0]));
  164. json_object_set_new(rootJ, "fcn_channel_2", json_integer((int)settings_.function[1]));
  165. json_t *potValuesJ = json_array();
  166. for (int p : pot_value_) {
  167. json_t *pJ = json_integer(p);
  168. json_array_append_new(potValuesJ, pJ);
  169. }
  170. json_object_set_new(rootJ, "pot_values", potValuesJ);
  171. json_object_set_new(rootJ, "snap_mode", json_boolean(settings_.snap_mode));
  172. return rootJ;
  173. }
  174. void fromJson(json_t *rootJ) override {
  175. json_t *editModeJ = json_object_get(rootJ, "edit_mode");
  176. if (editModeJ) {
  177. settings_.edit_mode = static_cast<EditMode>(json_integer_value(editModeJ));
  178. }
  179. json_t *fcnChannel1J = json_object_get(rootJ, "fcn_channel_1");
  180. if (fcnChannel1J) {
  181. settings_.function[0] = static_cast<Function>(json_integer_value(fcnChannel1J));
  182. }
  183. json_t *fcnChannel2J = json_object_get(rootJ, "fcn_channel_2");
  184. if (fcnChannel2J) {
  185. settings_.function[1] = static_cast<Function>(json_integer_value(fcnChannel2J));
  186. }
  187. json_t *snapModeJ = json_object_get(rootJ, "snap_mode");
  188. if (snapModeJ) {
  189. settings_.snap_mode = json_boolean_value(snapModeJ);
  190. }
  191. json_t *potValuesJ = json_object_get(rootJ, "pot_values");
  192. size_t potValueId;
  193. json_t *pJ;
  194. json_array_foreach(potValuesJ, potValueId, pJ) {
  195. if (potValueId < sizeof(pot_value_) / sizeof(pot_value_)[0]) {
  196. settings_.pot_value[potValueId] = json_integer_value(pJ);
  197. }
  198. }
  199. // Update module internal state from settings.
  200. init();
  201. }
  202. void step() override {
  203. poll();
  204. pollPots();
  205. // Initialize "secret" number station mode.
  206. if (initNumberStation) {
  207. processors[0].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION);
  208. processors[1].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION);
  209. initNumberStation = false;
  210. }
  211. if (outputBuffer.empty()) {
  212. ioBuffer.Process(process);
  213. uint32_t external_gate_inputs = 0;
  214. external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0);
  215. external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0);
  216. uint32_t buttons = 0;
  217. buttons |= (params[TRIG_1_PARAM].value ? 1 : 0);
  218. buttons |= (params[TRIG_2_PARAM].value ? 2 : 0);
  219. uint32_t gate_inputs = external_gate_inputs | buttons;
  220. // Prepare sample rate conversion.
  221. // Peaks is sampling at 48kHZ.
  222. outputSrc.setRates(48000, engineGetSampleRate());
  223. int inLen = peaks::kBlockSize;
  224. int outLen = outputBuffer.capacity();
  225. Frame<2> f[peaks::kBlockSize];
  226. // Process an entire block of data from the IOBuffer.
  227. for (size_t k = 0; k < peaks::kBlockSize; ++k) {
  228. peaks::IOBuffer::Slice slice = ioBuffer.NextSlice(1);
  229. for (size_t i = 0; i < peaks::kNumChannels; ++i) {
  230. gate_flags[i] = peaks::ExtractGateFlags(
  231. gate_flags[i],
  232. gate_inputs & (1 << i));
  233. f[k].samples[i] = slice.block->output[i][slice.frame_index];
  234. }
  235. // A hack to make channel 1 aware of what's going on in channel 2. Used to
  236. // reset the sequencer.
  237. slice.block->input[0][slice.frame_index] = gate_flags[0] | (gate_flags[1] << 4) | (buttons & 8 ? peaks::GATE_FLAG_FROM_BUTTON : 0);
  238. slice.block->input[1][slice.frame_index] = gate_flags[1] | (buttons & 2 ? peaks::GATE_FLAG_FROM_BUTTON : 0);
  239. }
  240. outputSrc.process(f, &inLen, outputBuffer.endData(), &outLen);
  241. outputBuffer.endIncr(outLen);
  242. }
  243. // Update outputs.
  244. if (!outputBuffer.empty()) {
  245. Frame<2> f = outputBuffer.shift();
  246. // Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV.
  247. // TODO Check the output values against an actual device.
  248. outputs[OUT_1_OUTPUT].value = rescale(static_cast<float>(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f);
  249. outputs[OUT_2_OUTPUT].value = rescale(static_cast<float>(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f);
  250. }
  251. }
  252. inline Function function() const {
  253. return edit_mode_ == EDIT_MODE_SECOND ? function_[1] : function_[0];
  254. }
  255. void changeControlMode();
  256. void setFunction(uint8_t index, Function f);
  257. void onPotChanged(uint16_t id, uint16_t value);
  258. void onSwitchReleased(uint16_t id, uint16_t data);
  259. void saveState();
  260. void lockPots();
  261. void poll();
  262. void pollPots();
  263. void refreshLeds();
  264. long long getSystemTimeMs();
  265. };
  266. const peaks::ProcessorFunction Peaks::function_table_[FUNCTION_LAST][2] = {
  267. { peaks::PROCESSOR_FUNCTION_ENVELOPE, peaks::PROCESSOR_FUNCTION_ENVELOPE },
  268. { peaks::PROCESSOR_FUNCTION_LFO, peaks::PROCESSOR_FUNCTION_LFO },
  269. { peaks::PROCESSOR_FUNCTION_TAP_LFO, peaks::PROCESSOR_FUNCTION_TAP_LFO },
  270. { peaks::PROCESSOR_FUNCTION_BASS_DRUM, peaks::PROCESSOR_FUNCTION_SNARE_DRUM },
  271. { peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER, peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER },
  272. { peaks::PROCESSOR_FUNCTION_PULSE_SHAPER, peaks::PROCESSOR_FUNCTION_PULSE_SHAPER },
  273. { peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER, peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER },
  274. { peaks::PROCESSOR_FUNCTION_FM_DRUM, peaks::PROCESSOR_FUNCTION_FM_DRUM },
  275. };
  276. void Peaks::changeControlMode() {
  277. uint16_t parameters[4];
  278. for (int i = 0; i < 4; ++i) {
  279. parameters[i] = adc_value_[i];
  280. }
  281. if (edit_mode_ == EDIT_MODE_SPLIT) {
  282. processors[0].CopyParameters(&parameters[0], 2);
  283. processors[1].CopyParameters(&parameters[2], 2);
  284. processors[0].set_control_mode(peaks::CONTROL_MODE_HALF);
  285. processors[1].set_control_mode(peaks::CONTROL_MODE_HALF);
  286. }
  287. else if (edit_mode_ == EDIT_MODE_TWIN) {
  288. processors[0].CopyParameters(&parameters[0], 4);
  289. processors[1].CopyParameters(&parameters[0], 4);
  290. processors[0].set_control_mode(peaks::CONTROL_MODE_FULL);
  291. processors[1].set_control_mode(peaks::CONTROL_MODE_FULL);
  292. }
  293. else {
  294. processors[0].set_control_mode(peaks::CONTROL_MODE_FULL);
  295. processors[1].set_control_mode(peaks::CONTROL_MODE_FULL);
  296. }
  297. }
  298. void Peaks::setFunction(uint8_t index, Function f) {
  299. if (edit_mode_ == EDIT_MODE_SPLIT || edit_mode_ == EDIT_MODE_TWIN) {
  300. function_[0] = function_[1] = f;
  301. processors[0].set_function(function_table_[f][0]);
  302. processors[1].set_function(function_table_[f][1]);
  303. }
  304. else {
  305. function_[index] = f;
  306. processors[index].set_function(function_table_[f][index]);
  307. }
  308. }
  309. void Peaks::onSwitchReleased(uint16_t id, uint16_t data) {
  310. switch (id) {
  311. case SWITCH_TWIN_MODE:
  312. if (data > kLongPressDuration) {
  313. edit_mode_ = static_cast<EditMode>(
  314. (edit_mode_ + EDIT_MODE_FIRST) % EDIT_MODE_LAST);
  315. function_[0] = function_[1];
  316. processors[0].set_function(function_table_[function_[0]][0]);
  317. processors[1].set_function(function_table_[function_[0]][1]);
  318. lockPots();
  319. }
  320. else {
  321. if (edit_mode_ <= EDIT_MODE_SPLIT) {
  322. edit_mode_ = static_cast<EditMode>(EDIT_MODE_SPLIT - edit_mode_);
  323. }
  324. else {
  325. edit_mode_ = static_cast<EditMode>(EDIT_MODE_SECOND - (edit_mode_ & 1));
  326. lockPots();
  327. }
  328. }
  329. changeControlMode();
  330. saveState();
  331. break;
  332. case SWITCH_FUNCTION: {
  333. Function f = function();
  334. if (data > kLongPressDuration) {
  335. f = static_cast<Function>((f + FUNCTION_FIRST_ALTERNATE_FUNCTION) % FUNCTION_LAST);
  336. }
  337. else {
  338. if (f <= FUNCTION_DRUM_GENERATOR) {
  339. f = static_cast<Function>((f + 1) & 3);
  340. }
  341. else {
  342. f = static_cast<Function>(((f + 1) & 3) + FUNCTION_FIRST_ALTERNATE_FUNCTION);
  343. }
  344. }
  345. setFunction(edit_mode_ - EDIT_MODE_FIRST, f);
  346. saveState();
  347. }
  348. break;
  349. case SWITCH_GATE_TRIG_1:
  350. // no-op
  351. break;
  352. case SWITCH_GATE_TRIG_2:
  353. // no-op
  354. break;
  355. }
  356. }
  357. void Peaks::lockPots() {
  358. std::fill(
  359. &adc_threshold_[0],
  360. &adc_threshold_[kNumAdcChannels],
  361. kAdcThresholdLocked);
  362. std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false);
  363. }
  364. void Peaks::pollPots() {
  365. for (uint8_t i = 0; i < kNumAdcChannels; ++i) {
  366. adc_lp_[i] = (int32_t(params[KNOB_1_PARAM + i].value) + adc_lp_[i] * 7) >> 3;
  367. int32_t value = adc_lp_[i];
  368. int32_t current_value = adc_value_[i];
  369. if (value >= current_value + adc_threshold_[i] ||
  370. value <= current_value - adc_threshold_[i] ||
  371. !adc_threshold_[i]) {
  372. onPotChanged(i, value);
  373. adc_value_[i] = value;
  374. adc_threshold_[i] = kAdcThresholdUnlocked;
  375. }
  376. }
  377. }
  378. void Peaks::onPotChanged(uint16_t id, uint16_t value) {
  379. switch (edit_mode_) {
  380. case EDIT_MODE_TWIN:
  381. processors[0].set_parameter(id, value);
  382. processors[1].set_parameter(id, value);
  383. pot_value_[id] = value >> 8;
  384. break;
  385. case EDIT_MODE_SPLIT:
  386. if (id < 2) {
  387. processors[0].set_parameter(id, value);
  388. }
  389. else {
  390. processors[1].set_parameter(id - 2, value);
  391. }
  392. pot_value_[id] = value >> 8;
  393. break;
  394. case EDIT_MODE_FIRST:
  395. case EDIT_MODE_SECOND: {
  396. uint8_t index = id + (edit_mode_ - EDIT_MODE_FIRST) * 4;
  397. peaks::Processors* p = &processors[edit_mode_ - EDIT_MODE_FIRST];
  398. int16_t delta = static_cast<int16_t>(pot_value_[index]) - \
  399. static_cast<int16_t>(value >> 8);
  400. if (delta < 0) {
  401. delta = -delta;
  402. }
  403. if (!snap_mode_ || snapped_[id] || delta <= 2) {
  404. p->set_parameter(id, value);
  405. pot_value_[index] = value >> 8;
  406. snapped_[id] = true;
  407. }
  408. }
  409. break;
  410. case EDIT_MODE_LAST:
  411. break;
  412. }
  413. }
  414. long long Peaks::getSystemTimeMs() {
  415. return std::chrono::duration_cast<std::chrono::milliseconds>(
  416. std::chrono::steady_clock::now().time_since_epoch()
  417. ).count();
  418. }
  419. void Peaks::poll() {
  420. for (uint8_t i = 0; i < 2; ++i) {
  421. if (switches_[i].process(params[BUTTON_1_PARAM + i].value)) {
  422. press_time_[i] = getSystemTimeMs();
  423. }
  424. if (switches_[i].isHigh() && press_time_[i] != 0) {
  425. int32_t pressed_time = getSystemTimeMs() - press_time_[i];
  426. if (pressed_time > kLongPressDuration) {
  427. onSwitchReleased(SWITCH_TWIN_MODE + i, pressed_time);
  428. press_time_[i] = 0; // Inhibit next release event
  429. }
  430. }
  431. if (!switches_[i].isHigh() && press_time_[i] != 0) {
  432. int32_t delta = getSystemTimeMs() - press_time_[i] + 1;
  433. onSwitchReleased(SWITCH_TWIN_MODE + i, delta);
  434. press_time_[i] = 0; // Not in original code!
  435. }
  436. }
  437. refreshLeds();
  438. }
  439. void Peaks::saveState() {
  440. settings_.edit_mode = edit_mode_;
  441. settings_.function[0] = function_[0];
  442. settings_.function[1] = function_[1];
  443. std::copy(&pot_value_[0], &pot_value_[8], &settings_.pot_value[0]);
  444. settings_.snap_mode = snap_mode_;
  445. }
  446. void Peaks::refreshLeds() {
  447. uint8_t flash = (getSystemTimeMs() >> 7) & 7;
  448. switch (edit_mode_) {
  449. case EDIT_MODE_FIRST:
  450. lights[TWIN_MODE_LIGHT].value = (flash == 1) ? 1.0f : 0.0f;
  451. break;
  452. case EDIT_MODE_SECOND:
  453. lights[TWIN_MODE_LIGHT].value = (flash == 1 || flash == 3) ? 1.0f : 0.0f;
  454. break;
  455. default:
  456. lights[TWIN_MODE_LIGHT].value = (edit_mode_ & 1) ? 1.0f : 0.0f;
  457. break;
  458. }
  459. if ((getSystemTimeMs() & 256) && function() >= FUNCTION_FIRST_ALTERNATE_FUNCTION) {
  460. for (size_t i = 0; i < 4; ++i) {
  461. lights[FUNC_1_LIGHT + i].value = 0.0f;
  462. }
  463. }
  464. else {
  465. for (size_t i = 0; i < 4; ++i) {
  466. lights[FUNC_1_LIGHT + i].value = ((function() & 3) == i) ? 1.0f : 0.0f;
  467. }
  468. }
  469. uint8_t b[2];
  470. for (uint8_t i = 0; i < 2; ++i) {
  471. switch (function_[i]) {
  472. case FUNCTION_DRUM_GENERATOR:
  473. case FUNCTION_FM_DRUM_GENERATOR:
  474. b[i] = (int16_t) std::abs(gBrightness[i]) >> 8;
  475. b[i] = b[i] >= 255 ? 255 : b[i];
  476. break;
  477. case FUNCTION_LFO:
  478. case FUNCTION_TAP_LFO:
  479. case FUNCTION_MINI_SEQUENCER: {
  480. int32_t brightness = int32_t(gBrightness[i]) * 409 >> 8;
  481. brightness += 32768;
  482. brightness >>= 8;
  483. CONSTRAIN(brightness, 0, 255);
  484. b[i] = brightness;
  485. }
  486. break;
  487. default:
  488. b[i] = gBrightness[i] >> 7;
  489. break;
  490. }
  491. }
  492. if (processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) {
  493. uint8_t pattern = processors[0].number_station().digit()
  494. ^ processors[1].number_station().digit();
  495. for (size_t i = 0; i < 4; ++i) {
  496. lights[FUNC_1_LIGHT + i].value = (pattern & 1) ? 1.0f : 0.0f;
  497. pattern = pattern >> 1;
  498. }
  499. b[0] = processors[0].number_station().gate() ? 255 : 0;
  500. b[1] = processors[1].number_station().gate() ? 255 : 0;
  501. }
  502. lights[TRIG_1_LIGHT].value = rescale(static_cast<float>(b[0]), 0.0f, 255.0f, 0.0f, 1.0f);
  503. lights[TRIG_2_LIGHT].value = rescale(static_cast<float>(b[1]), 0.0f, 255.0f, 0.0f, 1.0f);
  504. }
  505. struct PeaksWidget : ModuleWidget {
  506. PeaksWidget(Peaks *module) : ModuleWidget(module) {
  507. setPanel(SVG::load(assetPlugin(plugin, "res/Peaks.svg")));
  508. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  509. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  510. addParam(ParamWidget::create<TL1105>(Vec(8.5, 52), module, Peaks::BUTTON_1_PARAM, 0.0f, 1.0f, 0.0f));
  511. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 74), module, Peaks::TWIN_MODE_LIGHT));
  512. addParam(ParamWidget::create<TL1105>(Vec(8.5, 89), module, Peaks::BUTTON_2_PARAM, 0.0f, 1.0f, 0.0f));
  513. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 111), module, Peaks::FUNC_1_LIGHT));
  514. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 126.75), module, Peaks::FUNC_2_LIGHT));
  515. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 142.5), module, Peaks::FUNC_3_LIGHT));
  516. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(11.88, 158), module, Peaks::FUNC_4_LIGHT));
  517. addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 51), module, Peaks::KNOB_1_PARAM, 0.0f, 65535.0f, 16384.0f));
  518. addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 115), module, Peaks::KNOB_2_PARAM, 0.0f, 65535.0f, 16384.0f));
  519. addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 179), module, Peaks::KNOB_3_PARAM, 0.0f, 65535.0f, 32678.0f));
  520. addParam(ParamWidget::create<Rogan1PSWhite>(Vec(61, 244), module, Peaks::KNOB_4_PARAM, 0.0f, 65535.0f, 32678.0f));
  521. addParam(ParamWidget::create<LEDBezel>(Vec(11, 188), module, Peaks::TRIG_1_PARAM, 0.0f, 1.0f, 0.0f));
  522. addParam(ParamWidget::create<LEDBezel>(Vec(11, 273), module, Peaks::TRIG_2_PARAM, 0.0f, 1.0f, 0.0f));
  523. addChild(ModuleLightWidget::create<LEDBezelLight<GreenLight>>(Vec(11, 188).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_1_LIGHT));
  524. addChild(ModuleLightWidget::create<LEDBezelLight<GreenLight>>(Vec(11, 273).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_2_LIGHT));
  525. addInput(Port::create<PJ301MPort>(Vec(10, 230), Port::INPUT, module, Peaks::GATE_1_INPUT));
  526. addInput(Port::create<PJ301MPort>(Vec(10, 315), Port::INPUT, module, Peaks::GATE_2_INPUT));
  527. addOutput(Port::create<PJ301MPort>(Vec(53, 315), Port::OUTPUT, module, Peaks::OUT_1_OUTPUT));
  528. addOutput(Port::create<PJ301MPort>(Vec(86, 315), Port::OUTPUT, module, Peaks::OUT_2_OUTPUT));
  529. }
  530. Menu *createContextMenu() override {
  531. Menu *menu = ModuleWidget::createContextMenu();
  532. Peaks *peaks = dynamic_cast<Peaks*>(this->module);
  533. struct SnapModeItem : MenuItem {
  534. Peaks *peaks;
  535. void onAction(EventAction &e) override {
  536. peaks->snap_mode_ = !peaks->snap_mode_;
  537. }
  538. void step() override {
  539. rightText = (peaks->snap_mode_) ? "✔" : "";
  540. MenuItem::step();
  541. }
  542. };
  543. struct NumberStationItem : MenuItem {
  544. Peaks *peaks;
  545. void onAction(EventAction &e) override {
  546. peaks->initNumberStation = true;
  547. }
  548. };
  549. menu->addChild(construct<MenuLabel>());
  550. menu->addChild(construct<SnapModeItem>(&SnapModeItem::text, "Snap Mode", &SnapModeItem::peaks, peaks));
  551. menu->addChild(construct<MenuLabel>());
  552. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Secret Modes"));
  553. menu->addChild(construct<NumberStationItem>(&NumberStationItem::text, "Number Station", &NumberStationItem::peaks, peaks));
  554. return menu;
  555. }
  556. };
  557. Model *modelPeaks = Model::create<Peaks, PeaksWidget>("Audible Instruments", "Peaks", "Percussive Synthesizer", UTILITY_TAG, LFO_TAG, DRUM_TAG);