Audio plugin host https://kx.studio/carla
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.

420 lines
13KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Controller.cpp - (Midi) Controllers implementation
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Author: Nasca Octavian Paul
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of version 2 of the GNU General Public License
  8. as published by the Free Software Foundation.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License (version 2 or later) for more details.
  13. You should have received a copy of the GNU General Public License (version 2)
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include "Controller.h"
  18. #include <math.h>
  19. #include <stdio.h>
  20. Controller::Controller()
  21. {
  22. defaults();
  23. resetall();
  24. }
  25. Controller::~Controller()
  26. {}
  27. void Controller::defaults()
  28. {
  29. setpitchwheelbendrange(200); //2 halftones
  30. expression.receive = 1;
  31. panning.depth = 64;
  32. filtercutoff.depth = 64;
  33. filterq.depth = 64;
  34. bandwidth.depth = 64;
  35. bandwidth.exponential = 0;
  36. modwheel.depth = 80;
  37. modwheel.exponential = 0;
  38. fmamp.receive = 1;
  39. volume.receive = 1;
  40. sustain.receive = 1;
  41. NRPN.receive = 1;
  42. portamento.portamento = 0;
  43. portamento.used = 0;
  44. portamento.proportional = 0;
  45. portamento.propRate = 80;
  46. portamento.propDepth = 90;
  47. portamento.receive = 1;
  48. portamento.time = 64;
  49. portamento.updowntimestretch = 64;
  50. portamento.pitchthresh = 3;
  51. portamento.pitchthreshtype = 1;
  52. portamento.noteusing = -1;
  53. resonancecenter.depth = 64;
  54. resonancebandwidth.depth = 64;
  55. initportamento(440.0f, 440.0f, false); // Now has a third argument
  56. setportamento(0);
  57. }
  58. void Controller::resetall()
  59. {
  60. setpitchwheel(0); //center
  61. setexpression(127);
  62. setpanning(64);
  63. setfiltercutoff(64);
  64. setfilterq(64);
  65. setbandwidth(64);
  66. setmodwheel(64);
  67. setfmamp(127);
  68. setvolume(127);
  69. setsustain(0);
  70. setresonancecenter(64);
  71. setresonancebw(64);
  72. //reset the NRPN
  73. NRPN.parhi = -1;
  74. NRPN.parlo = -1;
  75. NRPN.valhi = -1;
  76. NRPN.vallo = -1;
  77. }
  78. void Controller::setpitchwheel(int value)
  79. {
  80. pitchwheel.data = value;
  81. float cents = value / 8192.0f;
  82. cents *= pitchwheel.bendrange;
  83. pitchwheel.relfreq = powf(2, cents / 1200.0f);
  84. //fprintf(stderr,"%ld %ld -> %.3f\n",pitchwheel.bendrange,pitchwheel.data,pitchwheel.relfreq);fflush(stderr);
  85. }
  86. void Controller::setpitchwheelbendrange(unsigned short int value)
  87. {
  88. pitchwheel.bendrange = value;
  89. }
  90. void Controller::setexpression(int value)
  91. {
  92. expression.data = value;
  93. if(expression.receive != 0)
  94. expression.relvolume = value / 127.0f;
  95. else
  96. expression.relvolume = 1.0f;
  97. }
  98. void Controller::setpanning(int value)
  99. {
  100. panning.data = value;
  101. panning.pan = (value / 128.0f - 0.5f) * (panning.depth / 64.0f);
  102. }
  103. void Controller::setfiltercutoff(int value)
  104. {
  105. filtercutoff.data = value;
  106. filtercutoff.relfreq =
  107. (value - 64.0f) * filtercutoff.depth / 4096.0f * 3.321928f; //3.3219f..=ln2(10)
  108. }
  109. void Controller::setfilterq(int value)
  110. {
  111. filterq.data = value;
  112. filterq.relq = powf(30.0f, (value - 64.0f) / 64.0f * (filterq.depth / 64.0f));
  113. }
  114. void Controller::setbandwidth(int value)
  115. {
  116. bandwidth.data = value;
  117. if(bandwidth.exponential == 0) {
  118. float tmp = powf(25.0f, powf(bandwidth.depth / 127.0f, 1.5f)) - 1.0f;
  119. if((value < 64) && (bandwidth.depth >= 64))
  120. tmp = 1.0f;
  121. bandwidth.relbw = (value / 64.0f - 1.0f) * tmp + 1.0f;
  122. if(bandwidth.relbw < 0.01f)
  123. bandwidth.relbw = 0.01f;
  124. }
  125. else
  126. bandwidth.relbw =
  127. powf(25.0f, (value - 64.0f) / 64.0f * (bandwidth.depth / 64.0f));
  128. ;
  129. }
  130. void Controller::setmodwheel(int value)
  131. {
  132. modwheel.data = value;
  133. if(modwheel.exponential == 0) {
  134. float tmp =
  135. powf(25.0f, powf(modwheel.depth / 127.0f, 1.5f) * 2.0f) / 25.0f;
  136. if((value < 64) && (modwheel.depth >= 64))
  137. tmp = 1.0f;
  138. modwheel.relmod = (value / 64.0f - 1.0f) * tmp + 1.0f;
  139. if(modwheel.relmod < 0.0f)
  140. modwheel.relmod = 0.0f;
  141. }
  142. else
  143. modwheel.relmod =
  144. powf(25.0f, (value - 64.0f) / 64.0f * (modwheel.depth / 80.0f));
  145. }
  146. void Controller::setfmamp(int value)
  147. {
  148. fmamp.data = value;
  149. fmamp.relamp = value / 127.0f;
  150. if(fmamp.receive != 0)
  151. fmamp.relamp = value / 127.0f;
  152. else
  153. fmamp.relamp = 1.0f;
  154. }
  155. void Controller::setvolume(int value)
  156. {
  157. volume.data = value;
  158. if(volume.receive != 0)
  159. volume.volume = powf(0.1f, (127 - value) / 127.0f * 2.0f);
  160. else
  161. volume.volume = 1.0f;
  162. }
  163. void Controller::setsustain(int value)
  164. {
  165. sustain.data = value;
  166. if(sustain.receive != 0)
  167. sustain.sustain = ((value < 64) ? 0 : 1);
  168. else
  169. sustain.sustain = 0;
  170. }
  171. void Controller::setportamento(int value)
  172. {
  173. portamento.data = value;
  174. if(portamento.receive != 0)
  175. portamento.portamento = ((value < 64) ? 0 : 1);
  176. }
  177. int Controller::initportamento(float oldfreq,
  178. float newfreq,
  179. bool legatoflag)
  180. {
  181. portamento.x = 0.0f;
  182. if(legatoflag) { // Legato in progress
  183. if(portamento.portamento == 0)
  184. return 0;
  185. }
  186. else // No legato, do the original if...return
  187. if((portamento.used != 0) || (portamento.portamento == 0))
  188. return 0;
  189. ;
  190. float portamentotime = powf(100.0f, portamento.time / 127.0f) / 50.0f; //portamento time in seconds
  191. if(portamento.proportional) {
  192. //If there is a min(float,float) and a max(float,float) then they
  193. //could be used here
  194. //Linear functors could also make this nicer
  195. if(oldfreq > newfreq) //2 is the center of propRate
  196. portamentotime *=
  197. powf(oldfreq / newfreq
  198. / (portamento.propRate / 127.0f * 3 + .05),
  199. (portamento.propDepth / 127.0f * 1.6f + .2));
  200. else //1 is the center of propDepth
  201. portamentotime *=
  202. powf(newfreq / oldfreq
  203. / (portamento.propRate / 127.0f * 3 + .05),
  204. (portamento.propDepth / 127.0f * 1.6f + .2));
  205. }
  206. if((portamento.updowntimestretch >= 64) && (newfreq < oldfreq)) {
  207. if(portamento.updowntimestretch == 127)
  208. return 0;
  209. portamentotime *= powf(0.1f,
  210. (portamento.updowntimestretch - 64) / 63.0f);
  211. }
  212. if((portamento.updowntimestretch < 64) && (newfreq > oldfreq)) {
  213. if(portamento.updowntimestretch == 0)
  214. return 0;
  215. portamentotime *= powf(0.1f,
  216. (64.0f - portamento.updowntimestretch) / 64.0f);
  217. }
  218. //printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime);
  219. portamento.dx = synth->buffersize_f / (portamentotime * synth->samplerate_f);
  220. portamento.origfreqrap = oldfreq / newfreq;
  221. float tmprap = ((portamento.origfreqrap > 1.0f) ?
  222. (portamento.origfreqrap) :
  223. (1.0f / portamento.origfreqrap));
  224. float thresholdrap = powf(2.0f, portamento.pitchthresh / 12.0f);
  225. if((portamento.pitchthreshtype == 0) && (tmprap - 0.00001f > thresholdrap))
  226. return 0;
  227. if((portamento.pitchthreshtype == 1) && (tmprap + 0.00001f < thresholdrap))
  228. return 0;
  229. portamento.used = 1;
  230. portamento.freqrap = portamento.origfreqrap;
  231. return 1;
  232. }
  233. void Controller::updateportamento()
  234. {
  235. if(portamento.used == 0)
  236. return;
  237. portamento.x += portamento.dx;
  238. if(portamento.x > 1.0f) {
  239. portamento.x = 1.0f;
  240. portamento.used = 0;
  241. }
  242. portamento.freqrap =
  243. (1.0f - portamento.x) * portamento.origfreqrap + portamento.x;
  244. }
  245. void Controller::setresonancecenter(int value)
  246. {
  247. resonancecenter.data = value;
  248. resonancecenter.relcenter =
  249. powf(3.0f, (value - 64.0f) / 64.0f * (resonancecenter.depth / 64.0f));
  250. }
  251. void Controller::setresonancebw(int value)
  252. {
  253. resonancebandwidth.data = value;
  254. resonancebandwidth.relbw =
  255. powf(1.5f, (value - 64.0f) / 64.0f * (resonancebandwidth.depth / 127.0f));
  256. }
  257. //Returns 0 if there is NRPN or 1 if there is not
  258. int Controller::getnrpn(int *parhi, int *parlo, int *valhi, int *vallo)
  259. {
  260. if(NRPN.receive == 0)
  261. return 1;
  262. if((NRPN.parhi < 0) || (NRPN.parlo < 0) || (NRPN.valhi < 0)
  263. || (NRPN.vallo < 0))
  264. return 1;
  265. *parhi = NRPN.parhi;
  266. *parlo = NRPN.parlo;
  267. *valhi = NRPN.valhi;
  268. *vallo = NRPN.vallo;
  269. return 0;
  270. }
  271. void Controller::setparameternumber(unsigned int type, int value)
  272. {
  273. switch(type) {
  274. case C_nrpnhi:
  275. NRPN.parhi = value;
  276. NRPN.valhi = -1;
  277. NRPN.vallo = -1; //clear the values
  278. break;
  279. case C_nrpnlo:
  280. NRPN.parlo = value;
  281. NRPN.valhi = -1;
  282. NRPN.vallo = -1; //clear the values
  283. break;
  284. case C_dataentryhi:
  285. if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
  286. NRPN.valhi = value;
  287. break;
  288. case C_dataentrylo:
  289. if((NRPN.parhi >= 0) && (NRPN.parlo >= 0))
  290. NRPN.vallo = value;
  291. break;
  292. }
  293. }
  294. void Controller::add2XML(XMLwrapper *xml)
  295. {
  296. xml->addpar("pitchwheel_bendrange", pitchwheel.bendrange);
  297. xml->addparbool("expression_receive", expression.receive);
  298. xml->addpar("panning_depth", panning.depth);
  299. xml->addpar("filter_cutoff_depth", filtercutoff.depth);
  300. xml->addpar("filter_q_depth", filterq.depth);
  301. xml->addpar("bandwidth_depth", bandwidth.depth);
  302. xml->addpar("mod_wheel_depth", modwheel.depth);
  303. xml->addparbool("mod_wheel_exponential", modwheel.exponential);
  304. xml->addparbool("fm_amp_receive", fmamp.receive);
  305. xml->addparbool("volume_receive", volume.receive);
  306. xml->addparbool("sustain_receive", sustain.receive);
  307. xml->addparbool("portamento_receive", portamento.receive);
  308. xml->addpar("portamento_time", portamento.time);
  309. xml->addpar("portamento_pitchthresh", portamento.pitchthresh);
  310. xml->addpar("portamento_pitchthreshtype", portamento.pitchthreshtype);
  311. xml->addpar("portamento_portamento", portamento.portamento);
  312. xml->addpar("portamento_updowntimestretch", portamento.updowntimestretch);
  313. xml->addpar("portamento_proportional", portamento.proportional);
  314. xml->addpar("portamento_proprate", portamento.propRate);
  315. xml->addpar("portamento_propdepth", portamento.propDepth);
  316. xml->addpar("resonance_center_depth", resonancecenter.depth);
  317. xml->addpar("resonance_bandwidth_depth", resonancebandwidth.depth);
  318. }
  319. void Controller::getfromXML(XMLwrapper *xml)
  320. {
  321. pitchwheel.bendrange = xml->getpar("pitchwheel_bendrange",
  322. pitchwheel.bendrange,
  323. -6400,
  324. 6400);
  325. expression.receive = xml->getparbool("expression_receive",
  326. expression.receive);
  327. panning.depth = xml->getpar127("panning_depth", panning.depth);
  328. filtercutoff.depth = xml->getpar127("filter_cutoff_depth",
  329. filtercutoff.depth);
  330. filterq.depth = xml->getpar127("filter_q_depth", filterq.depth);
  331. bandwidth.depth = xml->getpar127("bandwidth_depth", bandwidth.depth);
  332. modwheel.depth = xml->getpar127("mod_wheel_depth", modwheel.depth);
  333. modwheel.exponential = xml->getparbool("mod_wheel_exponential",
  334. modwheel.exponential);
  335. fmamp.receive = xml->getparbool("fm_amp_receive",
  336. fmamp.receive);
  337. volume.receive = xml->getparbool("volume_receive",
  338. volume.receive);
  339. sustain.receive = xml->getparbool("sustain_receive",
  340. sustain.receive);
  341. portamento.receive = xml->getparbool("portamento_receive",
  342. portamento.receive);
  343. portamento.time = xml->getpar127("portamento_time",
  344. portamento.time);
  345. portamento.pitchthresh = xml->getpar127("portamento_pitchthresh",
  346. portamento.pitchthresh);
  347. portamento.pitchthreshtype = xml->getpar127("portamento_pitchthreshtype",
  348. portamento.pitchthreshtype);
  349. portamento.portamento = xml->getpar127("portamento_portamento",
  350. portamento.portamento);
  351. portamento.updowntimestretch = xml->getpar127(
  352. "portamento_updowntimestretch",
  353. portamento.updowntimestretch);
  354. portamento.proportional = xml->getpar127("portamento_proportional",
  355. portamento.proportional);
  356. portamento.propRate = xml->getpar127("portamento_proprate",
  357. portamento.propRate);
  358. portamento.propDepth = xml->getpar127("portamento_propdepth",
  359. portamento.propDepth);
  360. resonancecenter.depth = xml->getpar127("resonance_center_depth",
  361. resonancecenter.depth);
  362. resonancebandwidth.depth = xml->getpar127("resonance_bandwidth_depth",
  363. resonancebandwidth.depth);
  364. }