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.

302 lines
6.1KB

  1. #pragma once
  2. #include "ObjectCache.h"
  3. #include "Poly.h"
  4. #include "SinOscillator.h"
  5. template <class TBase>
  6. class CH10 : public TBase
  7. {
  8. public:
  9. CH10(struct Module * module) : TBase(module)
  10. {
  11. }
  12. CH10() : TBase()
  13. {
  14. }
  15. /**
  16. * re-calc everything that changes with sample
  17. * rate. Also everything that depends on baseFrequency.
  18. *
  19. * Only needs to be called once.
  20. */
  21. void init();
  22. enum ParamIds
  23. {
  24. A0_PARAM,
  25. A1_PARAM,
  26. A2_PARAM,
  27. A3_PARAM,
  28. A4_PARAM,
  29. A5_PARAM,
  30. A6_PARAM,
  31. A7_PARAM,
  32. A8_PARAM,
  33. A9_PARAM,
  34. B0_PARAM,
  35. B1_PARAM,
  36. B2_PARAM,
  37. B3_PARAM,
  38. B4_PARAM,
  39. B5_PARAM,
  40. B6_PARAM,
  41. B7_PARAM,
  42. B8_PARAM,
  43. B9_PARAM,
  44. A0B0_PARAM,
  45. A0B1_PARAM,
  46. A0B2_PARAM,
  47. A0B3_PARAM,
  48. A0B4_PARAM,
  49. A0B5_PARAM,
  50. A0B6_PARAM,
  51. A0B7_PARAM,
  52. A0B8_PARAM,
  53. A0B9_PARAM,
  54. A1B0_PARAM,
  55. A1B1_PARAM,
  56. A1B2_PARAM,
  57. A1B3_PARAM,
  58. A1B4_PARAM,
  59. A1B5_PARAM,
  60. A1B6_PARAM,
  61. A1B7_PARAM,
  62. A1B8_PARAM,
  63. A1B9_PARAM,
  64. A2B0_PARAM,
  65. A2B1_PARAM,
  66. A2B2_PARAM,
  67. A2B3_PARAM,
  68. A2B4_PARAM,
  69. A2B5_PARAM,
  70. A2B6_PARAM,
  71. A2B7_PARAM,
  72. A2B8_PARAM,
  73. A2B9_PARAM,
  74. A3B0_PARAM,
  75. A3B1_PARAM,
  76. A3B2_PARAM,
  77. A3B3_PARAM,
  78. A3B4_PARAM,
  79. A3B5_PARAM,
  80. A3B6_PARAM,
  81. A3B7_PARAM,
  82. A3B8_PARAM,
  83. A3B9_PARAM,
  84. A4B0_PARAM,
  85. A4B1_PARAM,
  86. A4B2_PARAM,
  87. A4B3_PARAM,
  88. A4B4_PARAM,
  89. A4B5_PARAM,
  90. A4B6_PARAM,
  91. A4B7_PARAM,
  92. A4B8_PARAM,
  93. A4B9_PARAM,
  94. A5B0_PARAM,
  95. A5B1_PARAM,
  96. A5B2_PARAM,
  97. A5B3_PARAM,
  98. A5B4_PARAM,
  99. A5B5_PARAM,
  100. A5B6_PARAM,
  101. A5B7_PARAM,
  102. A5B8_PARAM,
  103. A5B9_PARAM,
  104. A6B0_PARAM,
  105. A6B1_PARAM,
  106. A6B2_PARAM,
  107. A6B3_PARAM,
  108. A6B4_PARAM,
  109. A6B5_PARAM,
  110. A6B6_PARAM,
  111. A6B7_PARAM,
  112. A6B8_PARAM,
  113. A6B9_PARAM,
  114. A7B0_PARAM,
  115. A7B1_PARAM,
  116. A7B2_PARAM,
  117. A7B3_PARAM,
  118. A7B4_PARAM,
  119. A7B5_PARAM,
  120. A7B6_PARAM,
  121. A7B7_PARAM,
  122. A7B8_PARAM,
  123. A7B9_PARAM,
  124. A8B0_PARAM,
  125. A8B1_PARAM,
  126. A8B2_PARAM,
  127. A8B3_PARAM,
  128. A8B4_PARAM,
  129. A8B5_PARAM,
  130. A8B6_PARAM,
  131. A8B7_PARAM,
  132. A8B8_PARAM,
  133. A8B9_PARAM,
  134. A9B0_PARAM,
  135. A9B1_PARAM,
  136. A9B2_PARAM,
  137. A9B3_PARAM,
  138. A9B4_PARAM,
  139. A9B5_PARAM,
  140. A9B6_PARAM,
  141. A9B7_PARAM,
  142. A9B8_PARAM,
  143. A9B9_PARAM,
  144. AOCTAVE_PARAM,
  145. BOCTAVE_PARAM,
  146. ASEMI_PARAM,
  147. BSEMI_PARAM,
  148. ATUNE_PARAM,
  149. BTUNE_PARAM,
  150. NUM_PARAMS
  151. };
  152. enum InputIds
  153. {
  154. ACV_INPUT,
  155. BCV_INPUT,
  156. NUM_INPUTS
  157. };
  158. enum OutputIds
  159. {
  160. MIXED_OUTPUT,
  161. NUM_OUTPUTS
  162. };
  163. enum LightIds
  164. {
  165. NUM_LIGHTS
  166. };
  167. /**
  168. * Main processing entry point. Called every sample
  169. */
  170. void step() override;
  171. private:
  172. using Osc = SinOscillator<float, true>;
  173. std::function<float(float)> expLookup = ObjectCache<float>::getExp2Ex();
  174. static const int polyOrder = 10;
  175. class VCOState
  176. {
  177. public:
  178. SinOscillatorParams<float> sinParams;
  179. SinOscillatorState<float> sinState;
  180. Poly<double, polyOrder> poly;
  181. };
  182. VCOState vcoState[2];
  183. void updatePitch();
  184. void updateVCOs(int which);
  185. void updateAudio();
  186. void runVCOs(int which);
  187. void doOutput();
  188. };
  189. template <class TBase>
  190. inline void CH10<TBase>::init()
  191. {
  192. }
  193. template <class TBase>
  194. inline void CH10<TBase>::step()
  195. {
  196. updatePitch();
  197. updateAudio();
  198. }
  199. template <class TBase>
  200. inline void CH10<TBase>::updatePitch()
  201. {
  202. updateVCOs(0);
  203. updateVCOs(1);
  204. }
  205. template <class TBase>
  206. inline void CH10<TBase>::updateVCOs(int which)
  207. {
  208. const float cv = TBase::inputs[ACV_INPUT + which].value;
  209. // const float finePitch = TBase::params[FINE1_PARAM + delta].value / 12.0f;
  210. const float finePitch = 0;
  211. const float semiPitch = TBase::params[ASEMI_PARAM + which].value / 12.0f;
  212. float pitch = 1.0f + roundf(TBase::params[AOCTAVE_PARAM + which].value) +
  213. semiPitch +
  214. finePitch;
  215. pitch += cv;
  216. //
  217. const float q = float(log2(261.626)); // move up to pitch range of EvenVCO
  218. pitch += q;
  219. const float freq = expLookup(pitch);
  220. float time = freq * TBase::engineGetSampleTime();
  221. Osc::setFrequency(vcoState[which].sinParams, time);
  222. // vcos[osc].setNormalizedFreq(TBase::engineGetSampleTime() * freq,
  223. // TBase::engineGetSampleTime());
  224. }
  225. template <class TBase>
  226. inline void CH10<TBase>::runVCOs(int which)
  227. {
  228. CH10<TBase>::VCOState& vco = vcoState[which];
  229. float sinOsc = Osc::run(vco.sinState, vco.sinParams);
  230. vco.poly.run(sinOsc, 1);
  231. }
  232. template <class TBase>
  233. inline void CH10<TBase>::updateAudio()
  234. {
  235. runVCOs(0);
  236. runVCOs(1);
  237. doOutput();
  238. }
  239. template <class TBase>
  240. inline void CH10<TBase>::doOutput()
  241. {
  242. float sum = 0;
  243. int num = 0;
  244. for (int i = 0; i < polyOrder; ++i) {
  245. if (TBase::params[A0_PARAM + i].value > .5f) {
  246. sum += vcoState[0].poly.getOutput(i);
  247. ++num;
  248. }
  249. }
  250. for (int i = 0; i < polyOrder; ++i) {
  251. if (TBase::params[B0_PARAM + i].value > .5f) {
  252. sum += vcoState[1].poly.getOutput(i);
  253. ++num;
  254. }
  255. }
  256. for (int row = 0; row < 10; ++row) {
  257. for (int col = 0; col < 10; ++col) {
  258. //float x = gridCol1 + gridSize * (col+1);
  259. //float y = gridRow1 - row * gridSize;
  260. int id = CH10<Widget>::A0B0_PARAM + col + row * 10;
  261. if (TBase::params[id].value > .5f) {
  262. const float ring = vcoState[0].poly.getOutput(col) *
  263. vcoState[1].poly.getOutput(row);
  264. sum += ring;
  265. ++num;
  266. }
  267. }
  268. }
  269. TBase::outputs[MIXED_OUTPUT].value = sum / num;
  270. }