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.

633 lines
25KB

  1. #include "Module_multiOscillator.hpp"
  2. #include "util/math.hpp"
  3. #include "Widget_multiOscillator.hpp"
  4. const char* multiOscillator::WaveFormAbbr[WaveFormType::NUM_WAVEFORMS] = { "SIN", "TRI", "SAW", "SQR" };
  5. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  6. //::::::::::::: TS_Oscillator :::::::::::::::::::::::::::::
  7. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  8. //--------------------------------------------------------
  9. // TS_Oscillator()
  10. // @numOutWaveForms: (IN) The number of output waveforms we will have from this oscillator.
  11. //--------------------------------------------------------
  12. TS_Oscillator::TS_Oscillator(int numOutWaveForms)
  13. {
  14. numOutputWaveForms = numOutWaveForms;
  15. if (numOutputWaveForms < 1)
  16. numOutputWaveForms = 1;
  17. for (int i = 0; i < numOutputWaveForms; i++)
  18. {
  19. outputWaveforms.push_back(TS_OscillatorOutput());
  20. outputWaveforms[i].outputChannelNumber = i + 1;
  21. }
  22. initialize();
  23. return;
  24. }
  25. //--------------------------------------------------------
  26. // initialize()
  27. // Initialize (UI) values to default values.
  28. //--------------------------------------------------------
  29. void TS_Oscillator::initialize()
  30. {
  31. ui_amplitude_V = MOSC_AMPLITUDE_DEFAULT_V;
  32. ui_frequency_Hz = MOSC_FREQ_DEFAULT_HZ;
  33. ui_phaseShift_deg = MOSC_PHASE_SHIFT_DEFAULT_DEG;
  34. ui_offset_V = MOSC_OFFSET_DEFAULT_V;
  35. for (int i = 0; i < static_cast<int>(outputWaveforms.size()); i++)
  36. {
  37. outputWaveforms[i].initialize();
  38. }
  39. return;
  40. } // end initialize()
  41. //--------------------------------------------------------
  42. // serialize()
  43. // @returns : The TS_Oscillator json node.
  44. //--------------------------------------------------------
  45. json_t* TS_Oscillator::serialize()
  46. {
  47. json_t* rootJ = json_object();
  48. json_object_set_new(rootJ, "amplitude_V", json_real(ui_amplitude_V));
  49. json_object_set_new(rootJ, "frequency_Hz", json_real(ui_frequency_Hz));
  50. json_object_set_new(rootJ, "phaseShift_deg", json_real(ui_phaseShift_deg));
  51. json_object_set_new(rootJ, "offset_V", json_real(ui_offset_V));
  52. json_object_set_new(rootJ, "numWaveforms", json_integer(outputWaveforms.size()));
  53. json_t* waveformsJ = json_array();
  54. for (int i = 0; i < static_cast<int>(outputWaveforms.size()); i++)
  55. {
  56. json_array_append_new(waveformsJ, outputWaveforms[i].serialize());
  57. }
  58. json_object_set_new(rootJ, "waveforms", waveformsJ);
  59. return rootJ;
  60. } // end serialize()
  61. //--------------------------------------------------------
  62. // deserialize()
  63. // @rootJ : (IN) The TS_Oscillator json node.
  64. //--------------------------------------------------------
  65. void TS_Oscillator::deserialize(json_t* rootJ)
  66. {
  67. json_t* currJ = NULL;
  68. if (rootJ) {
  69. currJ = json_object_get(rootJ, "amplitude_V");
  70. if (currJ)
  71. ui_amplitude_V = json_real_value(currJ);
  72. currJ = json_object_get(rootJ, "frequency_Hz");
  73. if (currJ)
  74. ui_frequency_Hz = json_real_value(currJ);
  75. currJ = json_object_get(rootJ, "phaseShift_deg");
  76. if (currJ)
  77. ui_phaseShift_deg = json_real_value(currJ);
  78. currJ = json_object_get(rootJ, "offset_V");
  79. if (currJ)
  80. ui_offset_V = json_real_value(currJ);
  81. currJ = json_object_get(rootJ, "numWaveforms");
  82. if (currJ)
  83. numOutputWaveForms = json_integer_value(currJ);
  84. if (numOutputWaveForms > static_cast<int>(outputWaveforms.size()))
  85. numOutputWaveForms = static_cast<int>(outputWaveforms.size());
  86. json_t* waveformsJ = json_object_get(rootJ, "waveforms");
  87. for (int i = 0; i < numOutputWaveForms; i++)
  88. {
  89. currJ = json_array_get(waveformsJ, i);
  90. if (currJ)
  91. {
  92. outputWaveforms[i].deserialize(currJ);
  93. }
  94. }
  95. }
  96. } // end deserialize()
  97. //--------------------------------------------------------
  98. // setPhaseShift_deg()
  99. // @deg : (IN) The phase shift in degrees.
  100. //--------------------------------------------------------
  101. void TS_Oscillator::setPhaseShift_deg(float deg)
  102. {
  103. phaseShift_deg = deg;
  104. phaseShift_norm = deg / 360.0f;
  105. return;
  106. }
  107. //--------------------------------------------------------
  108. // calculatePhase()
  109. // @dt : (IN) Time elapsed.
  110. // @doSync : (IN) If sync / reset requested.
  111. // @returns: True if shifted phase has reset (gone over 1)
  112. //--------------------------------------------------------
  113. bool TS_Oscillator::calculatePhase(float dt, bool doSync)
  114. {
  115. bool waveReset = doSync;
  116. if (doSync)
  117. {
  118. phase = 0;
  119. }
  120. else
  121. {
  122. // VCO clamps this, not sure if we need to
  123. float dPhase = clamp(frequency_Hz * dt, 0.f, 0.5f);
  124. phase = eucmod(phase + dPhase, 1.0f);
  125. }
  126. float prevSPhi = shiftedPhase;
  127. shiftedPhase = eucmod(phase + phaseShift_norm, 1.0f);
  128. if (!waveReset)
  129. waveReset = prevSPhi > shiftedPhase;
  130. return waveReset;
  131. }
  132. //--------------------------------------------------------
  133. // calcSin()
  134. // Sine wave.
  135. // Calculate with amplitude and offset.
  136. // @phaseShift_n : (IN) Normalized phase shift (-1 to 1).
  137. //--------------------------------------------------------
  138. float TS_Oscillator::calcSin(float phaseShift_n)
  139. {
  140. return amplitude_V * sinf(eucmod(1.0f + shiftedPhase + phaseShift_n, 1.0f) * 2.0f * NVG_PI) + offset_V;
  141. } // end calcSin()
  142. //--------------------------------------------------------
  143. // calcRect()
  144. // Rectangle wave.
  145. // Calculate with amplitude and offset.
  146. // @phaseShift_n : (IN) Normalized phase shift (-1 to 1).
  147. // @pulseWidth_n : (IN) Normalized pulse width (0-1). Really should be like 0.01 to 0.99 or something.
  148. //--------------------------------------------------------
  149. float TS_Oscillator::calcRect(float phaseShift_n, float pulseWidth_n)
  150. {
  151. float val = 0.0f;
  152. if (eucmod(1.0f + shiftedPhase + phaseShift_n, 1.0f) < pulseWidth_n)
  153. val = amplitude_V;
  154. else
  155. val = -amplitude_V;
  156. return val + offset_V;
  157. } // end calcRect
  158. //--------------------------------------------------------
  159. // calcTri()
  160. // Triange wave.
  161. // Calculate with amplitude and offset.
  162. // @phaseShift_n : (IN) Normalized phase shift (-1 to 1).
  163. //--------------------------------------------------------
  164. float TS_Oscillator::calcTri(float phaseShift_n)
  165. {
  166. float p_n = eucmod(1.0f + shiftedPhase + phaseShift_n, 1.0f);
  167. float val = 0.0f;
  168. if (p_n < 0.25f)
  169. val = 4.0f * p_n; // 0 to 1 (positive slope)
  170. else if (p_n < 0.75f)
  171. val = 2.0f - 4.0f * p_n; // -1 to 0 (positive slope)
  172. else
  173. val = -4.0f + 4.f * p_n;
  174. return amplitude_V * val + offset_V;
  175. } // end calcTri()
  176. //--------------------------------------------------------
  177. // calcSaw()
  178. // Sawtooth wave.
  179. // Calculate with amplitude and offset. (centered around 0)
  180. // @phaseShift_n : (IN) Normalized phase shift (-1 to 1).
  181. // @posRamp: (IN) True for positive ramp, false for negative ramp.
  182. //--------------------------------------------------------
  183. float TS_Oscillator::calcSaw(float phaseShift_n, bool posRamp)
  184. {
  185. float p_n = eucmod(1.0f + shiftedPhase + phaseShift_n, 1.0f);
  186. float val = 0.0f;
  187. float a_v = 2 * amplitude_V;
  188. if (posRamp)
  189. val = -amplitude_V + a_v * p_n; // Going up /|/|/|
  190. else
  191. val = amplitude_V - a_v * p_n; // Going down \|\|\|
  192. return val + offset_V;
  193. } // end calcSaw()
  194. //--------------------------------------------------------
  195. // calcSin()
  196. // Calculates A*sin(wt + phi) + C.
  197. // A = amplitude_V, w = frequency_radiansps, phi = phaseShift_radians, C = offset_V.
  198. //--------------------------------------------------------
  199. float TS_Oscillator::calcSin()
  200. {
  201. return amplitude_V * sinf(shiftedPhase * 2.0f * NVG_PI) + offset_V;
  202. }
  203. //--------------------------------------------------------
  204. // calcSquare()
  205. // Pseudo calculates A*SIGN(sin(wt + phi)) + C.
  206. // A = amplitude_V, w = frequency_radiansps, phi = phaseShift_radians, C = offset_V.
  207. // SIGN() = +1 for positive, -1 for negative, 0 for 0.
  208. //--------------------------------------------------------
  209. float TS_Oscillator::calcSquare()
  210. {
  211. float val = 0.0f;
  212. if (shiftedPhase < 0.5f)
  213. val = amplitude_V;
  214. else
  215. val = -amplitude_V;
  216. return val + offset_V;
  217. }
  218. //--------------------------------------------------------
  219. // calcTri()
  220. // Pseudo calculates A*SIGN(sin(wt + phi)) + C.
  221. // A = amplitude_V, w = frequency_radiansps, phi = phaseShift_radians, C = offset_V.
  222. // SIGN() = +1 for positive, -1 for negative, 0 for 0.
  223. //--------------------------------------------------------
  224. float TS_Oscillator::calcTri()
  225. {
  226. float val = 0.0f;
  227. if (shiftedPhase < 0.25f)
  228. val = 4.0f * shiftedPhase; // 0 to 1 (positive slope)
  229. else if (shiftedPhase < 0.75f)
  230. val = 2.0f - 4.0f * shiftedPhase; // -1 to 0 (positive slope)
  231. else
  232. val = -4.0f + 4.f * shiftedPhase;
  233. return amplitude_V * val + offset_V;
  234. }
  235. //--------------------------------------------------------
  236. // calcSaw()
  237. // Sawtooth wave, positive ramp.
  238. //--------------------------------------------------------
  239. float TS_Oscillator::calcSaw()
  240. {
  241. float val = 0.0f;
  242. if (shiftedPhase < 0.5f)
  243. val = 2.f * shiftedPhase;
  244. else
  245. val = -2.f + 2.f * shiftedPhase;
  246. return amplitude_V * val + offset_V;
  247. }
  248. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  249. //::::::::::::: multiOscillator :::::::::::::::::::::::::::
  250. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  251. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  252. // multiOscillator()
  253. // Create a module with numOscillators oscillators.
  254. // @numOscillators: (IN) Number of oscillators
  255. // @numOscillatorOutputs: (IN) Number of oscillators.
  256. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  257. multiOscillator::multiOscillator(int numOscillators, int numOscillatorOutputs) :
  258. Module(NUM_PARAMS + numOscillators * (TS_Oscillator::OSCWF_NUM_PARAMS + numOscillatorOutputs * TS_OscillatorOutput::OUT_NUM_PARAMS),
  259. NUM_INPUTS + numOscillators * (TS_Oscillator::OSCWF_NUM_INPUTS + numOscillatorOutputs * TS_OscillatorOutput::OUT_NUM_INPUTS),
  260. NUM_OUTPUTS + numOscillators * (TS_Oscillator::OSCWF_NUM_OUTPUTS + numOscillatorOutputs * TS_OscillatorOutput::OUT_NUM_OUTPUTS),
  261. NUM_LIGHTS + numOscillators * (TS_Oscillator::OSCWF_NUM_LIGHTS + numOscillatorOutputs * TS_OscillatorOutput::BaseLightIds::OUT_NUM_LIGHTS))
  262. {
  263. this->numberOscillators = numOscillators;
  264. this->oscillators = new TS_Oscillator[numberOscillators];
  265. this->numOscillatorOutputs = numOscillatorOutputs;
  266. for (int i = 0; i < numOscillators; i++)
  267. {
  268. oscillators[i] = TS_Oscillator(numOscillatorOutputs);
  269. }
  270. //this->theOscillator = new TS_Oscillator(numOscillatorOutputs);
  271. initialOscillators();
  272. return;
  273. }
  274. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  275. // Clean up or ram.
  276. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  277. multiOscillator::~multiOscillator()
  278. {
  279. isInitialized = false;
  280. if (oscillators != NULL)
  281. delete[] oscillators;
  282. oscillators = NULL;
  283. return;
  284. }
  285. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  286. // reset(void)
  287. // Initialize values.
  288. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  289. void multiOscillator::reset()
  290. {
  291. for (int i = 0; i < numberOscillators; i++)
  292. {
  293. oscillators[i].initialize();
  294. }
  295. return;
  296. }
  297. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  298. // toJson(void)
  299. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  300. json_t *multiOscillator::toJson()
  301. {
  302. json_t* rootJ = json_object();
  303. // version
  304. json_object_set_new(rootJ, "version", json_integer(TROWA_INTERNAL_VERSION_INT));
  305. json_object_set_new(rootJ, "numOsc", json_integer(numberOscillators));
  306. json_object_set_new(rootJ, "numOutputs", json_integer(numOscillatorOutputs));
  307. json_t* oscillatorsJ = json_array();
  308. for (int i = 0; i < numberOscillators; i++)
  309. {
  310. // Input
  311. json_array_append_new(oscillatorsJ, oscillators[i].serialize());
  312. }
  313. json_object_set_new(rootJ, "oscillators", oscillatorsJ);
  314. return rootJ;
  315. } // end toJson()
  316. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  317. // fromJson(void)
  318. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  319. void multiOscillator::fromJson(json_t *rootJ)
  320. {
  321. json_t* currJ = NULL;
  322. int nOscillators = numberOscillators;
  323. currJ = json_object_get(rootJ, "numOsc");
  324. if (currJ)
  325. {
  326. nOscillators = json_integer_value(currJ);
  327. if (nOscillators > numberOscillators)
  328. nOscillators = numberOscillators;
  329. }
  330. currJ = json_object_get(rootJ, "numOutputs");
  331. if (currJ)
  332. {
  333. numOscillatorOutputs = json_integer_value(currJ);
  334. }
  335. json_t* oscillatorsJ = json_object_get(rootJ, "oscillators");
  336. for (int i = 0; i < nOscillators; i++)
  337. {
  338. currJ = json_array_get(oscillatorsJ, i);
  339. if (currJ)
  340. {
  341. oscillators[i].deserialize(currJ);
  342. }
  343. } // end loop through osccilators
  344. return;
  345. } // end fromJson()
  346. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  347. // step(void)
  348. // Process
  349. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  350. void multiOscillator::step()
  351. {
  352. float dt = engineGetSampleTime();
  353. // Get Oscillator CV and User Inputs
  354. for (int osc = 0; osc < numberOscillators; osc++)
  355. {
  356. bool sync = false;
  357. bool oscillatorReset = false; // If this oscillator is at 0 phase.
  358. TS_Oscillator* theOscillator = &(oscillators[osc]);
  359. int baseInputId = InputIds::OSC_INPUT_START + osc * (TS_Oscillator::BaseInputIds::OSCWF_NUM_INPUTS + numOscillatorOutputs * TS_OscillatorOutput::BaseInputIds::OUT_NUM_INPUTS);
  360. int baseParamId = ParamIds::OSC_PARAM_START + osc * (TS_Oscillator::BaseParamIds::OSCWF_NUM_PARAMS + numOscillatorOutputs * TS_OscillatorOutput::BaseParamIds::OUT_NUM_PARAMS);
  361. int baseOutputId = OutputIds::OSC_OUTPUT_START + osc * (TS_Oscillator::BaseOutputIds::OSCWF_NUM_OUTPUTS + numOscillatorOutputs * TS_OscillatorOutput::BaseOutputIds::OUT_NUM_OUTPUTS);
  362. int baseLightId = LightIds::OSC_LIGHT_START + osc * (TS_Oscillator::BaseLightIds::OSCWF_NUM_LIGHTS + numOscillatorOutputs * TS_OscillatorOutput::BaseLightIds::OUT_NUM_LIGHTS);
  363. //------------------------------
  364. // Sync this oscillator
  365. //------------------------------
  366. if (lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value > 0)
  367. lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value -= lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value / lightLambda * dt;
  368. else if (lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value < 0)
  369. lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value = 0;
  370. if (theOscillator->synchTrigger.process(params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_SYNC_PARAM].value + inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_SYNC_INPUT].value))
  371. {
  372. lights[baseLightId + TS_Oscillator::BaseLightIds::OSCWF_SYNC_LED].value = 1.0f;
  373. sync = true;
  374. } // end if
  375. //------------------------------
  376. // Values In (Add Input + Knob)
  377. //------------------------------
  378. // *> Amplitude (V):
  379. theOscillator->ui_amplitude_V = params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_AMPLITUDE_PARAM].value;
  380. float a = theOscillator->ui_amplitude_V;
  381. if (inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_AMPLITUDE_INPUT].active)
  382. a += inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_AMPLITUDE_INPUT].value;
  383. theOscillator->amplitude_V = a;
  384. // *> Frequency (Hz):
  385. // User Knob:
  386. #if TROWA_MOSC_FREQ_KNOB_NEEDS_CONVERSION
  387. theOscillator->ui_frequency_Hz = rescale(params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_FREQUENCY_PARAM].value, TROWA_MOSC_F_KNOB_MIN_V, TROWA_MOSC_F_KNOB_MAX_V, MOSC_FREQ_MIN_HZ, MOSC_FREQ_MAX_HZ);
  388. #else
  389. theOscillator->ui_frequency_Hz = params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_FREQUENCY_PARAM].value;
  390. #endif
  391. float f = theOscillator->ui_frequency_Hz;
  392. // Add Input:
  393. if (inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_FREQUENCY_INPUT].active) {
  394. // CV frequency
  395. f = clamp(f + VoltageToFrequency(inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_FREQUENCY_INPUT].value), MOSC_FREQ_MIN_HZ, MOSC_FREQ_MAX_HZ);
  396. }
  397. theOscillator->frequency_Hz = f; // Actual Frequency
  398. // *> Phase Shift (deg):
  399. theOscillator->ui_phaseShift_deg = rescale(params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_PHASE_SHIFT_PARAM].value, TROWA_MOSC_KNOB_MIN_V, TROWA_MOSC_KNOB_MAX_V, MOSC_PHASE_SHIFT_MIN_DEG, MOSC_PHASE_SHIFT_MAX_DEG);
  400. float phi = theOscillator->ui_phaseShift_deg;
  401. if (inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_PHASE_SHIFT_INPUT].active) {
  402. phi += rescale(inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_PHASE_SHIFT_INPUT].value, TROWA_MOSC_INPUT_MIN_V, TROWA_MOSC_INPUT_MAX_V, MOSC_PHASE_SHIFT_MIN_DEG, MOSC_PHASE_SHIFT_MAX_DEG);
  403. }
  404. theOscillator->setPhaseShift_deg(phi);
  405. // *> Offset (V):
  406. theOscillator->ui_offset_V = params[baseParamId + TS_Oscillator::BaseParamIds::OSCWF_OFFSET_PARAM].value;
  407. float c = theOscillator->ui_offset_V;
  408. if (inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_OFFSET_INPUT].active)
  409. c += inputs[baseInputId + TS_Oscillator::BaseInputIds::OSCWF_OFFSET_INPUT].value;
  410. theOscillator->offset_V = c;
  411. //------------------------------
  412. // Calculate phase
  413. //------------------------------
  414. oscillatorReset = theOscillator->calculatePhase(dt, sync);
  415. //------------------------------
  416. // Sync Output
  417. //------------------------------
  418. if (oscillatorReset)
  419. {
  420. theOscillator->synchPulse.trigger(1e-4); // 1e-3
  421. }
  422. outputs[baseOutputId + TS_Oscillator::BaseOutputIds::OSCWF_SYNC_OUTPUT].value = (theOscillator->synchPulse.process(dt)) ? 10.0f : 0.0f;
  423. //------------------------------
  424. // Each output channel
  425. //------------------------------
  426. baseParamId += TS_Oscillator::BaseParamIds::OSCWF_NUM_PARAMS;
  427. baseInputId += TS_Oscillator::BaseInputIds::OSCWF_NUM_INPUTS;
  428. baseOutputId += TS_Oscillator::BaseOutputIds::OSCWF_NUM_OUTPUTS;
  429. baseLightId += TS_Oscillator::BaseLightIds::OSCWF_NUM_LIGHTS;
  430. for (int i = 0; i < theOscillator->numOutputWaveForms; i++)
  431. {
  432. float type = clamp((int)rescale(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_OSC_TYPE_PARAM].value, TROWA_MOSC_KNOB_MIN_V, TROWA_MOSC_KNOB_MAX_V, 0, WaveFormType::NUM_WAVEFORMS), 0, WaveFormType::NUM_WAVEFORMS - 1);
  433. theOscillator->outputWaveforms[i].ui_waveFormType = static_cast<WaveFormType>(int(type));
  434. if (inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_OSC_TYPE_INPUT].active) {
  435. type = clamp((int)rescale(inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_OSC_TYPE_INPUT].value,
  436. TROWA_MOSC_TYPE_INPUT_MIN_V, TROWA_MOSC_TYPE_INPUT_MAX_V, 0, WaveFormType::NUM_WAVEFORMS), 0, WaveFormType::NUM_WAVEFORMS - 1);
  437. }
  438. theOscillator->outputWaveforms[i].waveFormType = static_cast<WaveFormType>(int(type));
  439. // *> Phase shift for this output
  440. float phi = rescale(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_PHASE_SHIFT_PARAM].value,
  441. TROWA_MOSC_KNOB_MIN_V, TROWA_MOSC_KNOB_MAX_V,
  442. MOSC_PHASE_SHIFT_MIN_DEG, MOSC_PHASE_SHIFT_MAX_DEG);
  443. theOscillator->outputWaveforms[i].ui_phaseShift_deg = phi;
  444. if (inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_PHASE_SHIFT_INPUT].active) {
  445. phi += rescale(inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_PHASE_SHIFT_INPUT].value,
  446. TROWA_MOSC_INPUT_MIN_V, TROWA_MOSC_INPUT_MAX_V, MOSC_PHASE_SHIFT_MIN_DEG, MOSC_PHASE_SHIFT_MAX_DEG);
  447. }
  448. theOscillator->outputWaveforms[i].setPhaseShift_deg(phi);
  449. // *> Aux parameter: (Currently only rect/square and saw/ramp)
  450. float aux = 0.5f;
  451. //switch (theOscillator->outputWaveforms[i].waveFormType)
  452. //{
  453. //case WaveFormType::WAVEFORM_SQR:
  454. //case WaveFormType::WAVEFORM_SAW:
  455. // aux = rescale(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AUX_PARAM].value, TROWA_MOSC_AUX_MIN_V, TROWA_MOSC_AUX_MAX_V, 0.0f, 1.0f);
  456. // break;
  457. //default:
  458. // break;
  459. //}
  460. if (inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_AUX_INPUT].active) {
  461. aux = clamp(rescale(inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_AUX_INPUT].value, TROWA_MOSC_AUX_MIN_V, TROWA_MOSC_AUX_MAX_V, 0.f, 1.f), 0.f, 1.f);
  462. }
  463. else
  464. {
  465. aux = rescale(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AUX_PARAM].value, TROWA_MOSC_KNOB_AUX_MIN_V, TROWA_MOSC_KNOB_AUX_MAX_V, 0.0f, 1.0f);
  466. }
  467. theOscillator->outputWaveforms[i].auxParam_norm = aux;
  468. // *> AM Type (digital = false, ring = true)
  469. if (theOscillator->outputWaveforms[i].amRingModulationTrigger.process(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AM_TYPE_PARAM].value))
  470. {
  471. theOscillator->outputWaveforms[i].amRingModulation = !theOscillator->outputWaveforms[i].amRingModulation;
  472. //info("[Ch %d] AM Button Click id %d. Ring Mod = %d.", i + 1, baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AM_TYPE_PARAM, theOscillator->outputWaveforms[i].amRingModulation);
  473. }
  474. lights[baseLightId + TS_OscillatorOutput::BaseLightIds::OUT_AM_MODE_LED].value = (theOscillator->outputWaveforms[i].amRingModulation) ? 1.0f : 0.0f;
  475. //------------------------------------------
  476. // Calculate an output/outputs
  477. //------------------------------------------
  478. if (outputs[baseOutputId + TS_OscillatorOutput::BaseOutputIds::OUT_RAW_SIGNAL].active ||
  479. (outputs[baseOutputId + TS_OscillatorOutput::BaseOutputIds::OUT_MULTIPLIED_SIGNAL].active && inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_AM_INPUT].active))
  480. {
  481. // Calculate the RAW output:
  482. float rawOutput = 0.0f;
  483. float phi_n = theOscillator->outputWaveforms[i].phaseShift_norm;
  484. switch (theOscillator->outputWaveforms[i].waveFormType)
  485. {
  486. case WaveFormType::WAVEFORM_SIN:
  487. rawOutput = theOscillator->calcSin(phi_n);
  488. break;
  489. case WaveFormType::WAVEFORM_TRI:
  490. rawOutput = theOscillator->calcTri(phi_n);
  491. break;
  492. case WaveFormType::WAVEFORM_SQR:
  493. rawOutput = theOscillator->calcRect(phi_n, theOscillator->outputWaveforms[i].auxParam_norm);
  494. break;
  495. case WaveFormType::WAVEFORM_SAW:
  496. rawOutput = theOscillator->calcSaw(phi_n, theOscillator->outputWaveforms[i].getRampSlope());
  497. break;
  498. default:
  499. break;
  500. }
  501. outputs[baseOutputId + TS_OscillatorOutput::BaseOutputIds::OUT_RAW_SIGNAL].value = rawOutput;
  502. // Calculate AM output:
  503. if (outputs[baseOutputId + TS_OscillatorOutput::BaseOutputIds::OUT_MULTIPLIED_SIGNAL].active)
  504. {
  505. float modOutput = 0.f;
  506. float modulator = inputs[baseInputId + TS_OscillatorOutput::BaseInputIds::OUT_AM_INPUT].value;
  507. float modWeight = params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AM_MIX_PARAM].value; //rescale(params[baseParamId + TS_OscillatorOutput::BaseParamIds::OUT_AM_MIX_PARAM].value, TROWA_MOSC_KNOB_MIN_V, TROWA_MOSC_KNOB_MAX_V, 0.f, 1.f)
  508. if (theOscillator->outputWaveforms[i].amRingModulation)
  509. {
  510. // Ring modulation
  511. modOutput = theOscillator->ringModulator.ringMod(modulator, rawOutput);
  512. }
  513. else
  514. {
  515. // Digital modulation (just mulitply)
  516. modOutput = modulator * rawOutput;
  517. }
  518. outputs[baseOutputId + TS_OscillatorOutput::BaseOutputIds::OUT_MULTIPLIED_SIGNAL].value = modWeight * modOutput + (1.0f - modWeight)*rawOutput;
  519. } // end calculate the multiplied signal
  520. } // end calculate the raw signal
  521. baseParamId += TS_OscillatorOutput::BaseParamIds::OUT_NUM_PARAMS;
  522. baseInputId += TS_OscillatorOutput::BaseInputIds::OUT_NUM_INPUTS;
  523. baseOutputId += TS_OscillatorOutput::BaseOutputIds::OUT_NUM_OUTPUTS;
  524. baseLightId += TS_OscillatorOutput::BaseLightIds::OUT_NUM_LIGHTS;
  525. } // end loop through output signals/channels
  526. } // end loop through oscillators
  527. return;
  528. } // end step()
  529. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  530. //::::::::::::: TS_OscillatorOutput :::::::::::::::::::::::::::::
  531. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  532. //--------------------------------------------------------
  533. // initialize()
  534. //--------------------------------------------------------
  535. void TS_OscillatorOutput::initialize()
  536. {
  537. phaseShift_deg = 0;
  538. phaseShift_norm = 0;
  539. amRingModulation = false;
  540. auxParam_norm = 0.5f;
  541. return;
  542. }
  543. //--------------------------------------------------------
  544. // setPhaseShift_deg()
  545. // @deg : (IN) The phase shift in degrees.
  546. //--------------------------------------------------------
  547. void TS_OscillatorOutput::setPhaseShift_deg(float deg)
  548. {
  549. phaseShift_deg = deg;
  550. phaseShift_norm = deg / 360.0f;
  551. return;
  552. }
  553. //--------------------------------------------------------
  554. // serialize()
  555. // @returns : The TS_Oscillator json node.
  556. //--------------------------------------------------------
  557. json_t* TS_OscillatorOutput::serialize()
  558. {
  559. json_t* rootJ = json_object();
  560. json_object_set_new(rootJ, "wavetype", json_integer(waveFormType));
  561. json_object_set_new(rootJ, "phaseShift_deg", json_real(ui_phaseShift_deg));
  562. json_object_set_new(rootJ, "auxParam_norm", json_real(auxParam_norm));
  563. json_object_set_new(rootJ, "amRingMod", json_integer(amRingModulation));
  564. return rootJ;
  565. } // end serialize()
  566. //--------------------------------------------------------
  567. // deserialize()
  568. // @rootJ : (IN) The TS_Oscillator json node.
  569. //--------------------------------------------------------
  570. void TS_OscillatorOutput::deserialize(json_t* rootJ)
  571. {
  572. json_t* currJ = NULL;
  573. if (rootJ) {
  574. currJ = json_object_get(rootJ, "wavetype");
  575. if (currJ)
  576. waveFormType = static_cast<WaveFormType>( json_integer_value(currJ) );
  577. currJ = json_object_get(rootJ, "phaseShift_deg");
  578. if (currJ)
  579. ui_phaseShift_deg = json_real_value(currJ);
  580. currJ = json_object_get(rootJ, "auxParam_norm");
  581. if (currJ)
  582. auxParam_norm = json_real_value(currJ);
  583. currJ = json_object_get(rootJ, "amRingMod");
  584. if (currJ)
  585. amRingModulation = json_integer_value(currJ) > 0;
  586. }
  587. } // end deserialize()
  588. // Model for trowa multiOscillator
  589. RACK_PLUGIN_MODEL_INIT(trowaSoft, MultiOscillator) {
  590. Model* modelMultiOscillator = Model::create<multiOscillator, multiOscillatorWidget>(/*manufacturer*/ TROWA_PLUGIN_NAME, /*slug*/ "multiWave", /*name*/ "multiWave", /*Tags*/ OSCILLATOR_TAG, RING_MODULATOR_TAG);
  591. return modelMultiOscillator;
  592. }