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.

423 lines
11KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. EnvelopeParams.cpp - Parameters for Envelope
  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
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include <cmath>
  12. #include <cstdlib>
  13. #include <cassert>
  14. #include <rtosc/ports.h>
  15. #include <rtosc/port-sugar.h>
  16. #include "EnvelopeParams.h"
  17. #include "../Misc/Util.h"
  18. #include "../Misc/Time.h"
  19. #define rObject EnvelopeParams
  20. using namespace rtosc;
  21. #define rBegin [](const char *msg, RtData &d) { \
  22. EnvelopeParams *env = (rObject*) d.obj
  23. #define rEnd }
  24. static const rtosc::Ports localPorts = {
  25. rSelf(EnvelopeParams),
  26. rPaste,
  27. #undef rChangeCb
  28. #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); if (obj->time) { \
  29. obj->last_update_timestamp = obj->time->time(); }
  30. rToggle(Pfreemode, "Complex Envelope Definitions"),
  31. #undef rChangeCb
  32. #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); \
  33. if(obj->time) { obj->last_update_timestamp = obj->time->time(); }
  34. rParamZyn(Penvpoints, rProp(internal), "Number of points in complex definition"),
  35. rParamZyn(Penvsustain, rProp(internal), "Location of the sustain point"),
  36. rParams(Penvdt, MAX_ENVELOPE_POINTS, "Envelope Delay Times"),
  37. rParams(Penvval, MAX_ENVELOPE_POINTS, "Envelope Values"),
  38. rParamZyn(Penvstretch, rShort("stretch"),
  39. "Stretch with respect to frequency"),
  40. rToggle(Pforcedrelease, rShort("frcr"),
  41. "Force Envelope to fully evaluate"),
  42. rToggle(Plinearenvelope, rShort("lin/log"),
  43. "Linear or Logarithmic Envelopes"),
  44. rParamZyn(PA_dt, rShort("a.dt"), "Attack Time"),
  45. rParamZyn(PA_val, rShort("a.val"), "Attack Value"),
  46. rParamZyn(PD_dt, rShort("d.dt"), "Decay Time"),
  47. rParamZyn(PD_val, rShort("d.val"), "Decay Value"),
  48. rParamZyn(PS_val, rShort("s.val"), "Sustain Value"),
  49. rParamZyn(PR_dt, rShort("r.dt"), "Release Time"),
  50. rParamZyn(PR_val, rShort("r.val"), "Release Value"),
  51. {"envdt:", rDoc("Envelope Delay Times"), NULL,
  52. rBegin;
  53. const int N = MAX_ENVELOPE_POINTS;
  54. rtosc_arg_t args[N];
  55. char arg_types[N+1] = {0};
  56. for(int i=0; i<N; ++i) {
  57. args[i].f = env->getdt(i);
  58. arg_types[i] = 'f';
  59. }
  60. d.replyArray(d.loc, arg_types, args);
  61. rEnd},
  62. {"envval:", rDoc("Envelope Delay Times"), NULL,
  63. rBegin;
  64. const int N = MAX_ENVELOPE_POINTS;
  65. rtosc_arg_t args[N];
  66. char arg_types[N+1] = {0};
  67. for(int i=0; i<N; ++i) {
  68. args[i].f = env->Penvval[i]/127.0f;
  69. arg_types[i] = 'f';
  70. }
  71. d.replyArray(d.loc, arg_types, args);
  72. rEnd},
  73. {"addPoint:i", rProp(internal) rDoc("Add point to envelope"), NULL,
  74. rBegin;
  75. const int curpoint = rtosc_argument(msg, 0).i;
  76. //int curpoint=freeedit->lastpoint;
  77. if (curpoint<0 || curpoint>env->Penvpoints || env->Penvpoints>=MAX_ENVELOPE_POINTS)
  78. return;
  79. for (int i=env->Penvpoints; i>=curpoint+1; i--) {
  80. env->Penvdt[i]=env->Penvdt[i-1];
  81. env->Penvval[i]=env->Penvval[i-1];
  82. }
  83. if (curpoint==0)
  84. env->Penvdt[1]=64;
  85. env->Penvpoints++;
  86. if (curpoint<=env->Penvsustain)
  87. env->Penvsustain++;
  88. rEnd},
  89. {"delPoint:i", rProp(internal) rDoc("Delete Envelope Point"), NULL,
  90. rBegin;
  91. const int curpoint=rtosc_argument(msg, 0).i;
  92. if(curpoint<1 || curpoint>=env->Penvpoints-1 || env->Penvpoints<=3)
  93. return;
  94. for (int i=curpoint+1;i<env->Penvpoints;i++){
  95. env->Penvdt[i-1]=env->Penvdt[i];
  96. env->Penvval[i-1]=env->Penvval[i];
  97. };
  98. env->Penvpoints--;
  99. if (curpoint<=env->Penvsustain)
  100. env->Penvsustain--;
  101. rEnd},
  102. };
  103. #undef rChangeCb
  104. const rtosc::Ports &EnvelopeParams::ports = localPorts;
  105. EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_,
  106. unsigned char Pforcedrelease_,
  107. const AbsTime *time_):
  108. time(time_), last_update_timestamp(0)
  109. {
  110. PA_dt = 10;
  111. PD_dt = 10;
  112. PR_dt = 10;
  113. PA_val = 64;
  114. PD_val = 64;
  115. PS_val = 64;
  116. PR_val = 64;
  117. for(int i = 0; i < MAX_ENVELOPE_POINTS; ++i) {
  118. Penvdt[i] = 32;
  119. Penvval[i] = 64;
  120. }
  121. Penvdt[0] = 0; //no used
  122. Penvsustain = 1;
  123. Penvpoints = 1;
  124. Envmode = 1;
  125. Penvstretch = Penvstretch_;
  126. Pforcedrelease = Pforcedrelease_;
  127. Pfreemode = 1;
  128. Plinearenvelope = 0;
  129. store2defaults();
  130. }
  131. EnvelopeParams::~EnvelopeParams()
  132. {}
  133. #define COPY(y) this->y = ep.y
  134. void EnvelopeParams::paste(const EnvelopeParams &ep)
  135. {
  136. COPY(Pfreemode);
  137. COPY(Penvpoints);
  138. COPY(Penvsustain);
  139. for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) {
  140. this->Penvdt[i] = ep.Penvdt[i];
  141. this->Penvval[i] = ep.Penvval[i];
  142. }
  143. COPY(Penvstretch);
  144. COPY(Pforcedrelease);
  145. COPY(Plinearenvelope);
  146. COPY(PA_dt);
  147. COPY(PD_dt);
  148. COPY(PR_dt);
  149. COPY(PA_val);
  150. COPY(PD_val);
  151. COPY(PS_val);
  152. COPY(PR_val);
  153. if ( time ) {
  154. last_update_timestamp = time->time();
  155. }
  156. }
  157. #undef COPY
  158. float EnvelopeParams::getdt(char i) const
  159. {
  160. return EnvelopeParams::dt(Penvdt[(int)i]);
  161. }
  162. float EnvelopeParams::dt(char val)
  163. {
  164. return (powf(2.0f, val / 127.0f * 12.0f) - 1.0f) * 10.0f; //miliseconds
  165. }
  166. /*
  167. * ADSR/ASR... initialisations
  168. */
  169. void EnvelopeParams::ADSRinit(char A_dt, char D_dt, char S_val, char R_dt)
  170. {
  171. setpresettype("Penvamplitude");
  172. Envmode = 1;
  173. PA_dt = A_dt;
  174. PD_dt = D_dt;
  175. PS_val = S_val;
  176. PR_dt = R_dt;
  177. Pfreemode = 0;
  178. converttofree();
  179. store2defaults();
  180. }
  181. void EnvelopeParams::ADSRinit_dB(char A_dt, char D_dt, char S_val, char R_dt)
  182. {
  183. setpresettype("Penvamplitude");
  184. Envmode = 2;
  185. PA_dt = A_dt;
  186. PD_dt = D_dt;
  187. PS_val = S_val;
  188. PR_dt = R_dt;
  189. Pfreemode = 0;
  190. converttofree();
  191. store2defaults();
  192. }
  193. void EnvelopeParams::ASRinit(char A_val, char A_dt, char R_val, char R_dt)
  194. {
  195. setpresettype("Penvfrequency");
  196. Envmode = 3;
  197. PA_val = A_val;
  198. PA_dt = A_dt;
  199. PR_val = R_val;
  200. PR_dt = R_dt;
  201. Pfreemode = 0;
  202. converttofree();
  203. store2defaults();
  204. }
  205. void EnvelopeParams::ADSRinit_filter(char A_val,
  206. char A_dt,
  207. char D_val,
  208. char D_dt,
  209. char R_dt,
  210. char R_val)
  211. {
  212. setpresettype("Penvfilter");
  213. Envmode = 4;
  214. PA_val = A_val;
  215. PA_dt = A_dt;
  216. PD_val = D_val;
  217. PD_dt = D_dt;
  218. PR_dt = R_dt;
  219. PR_val = R_val;
  220. Pfreemode = 0;
  221. converttofree();
  222. store2defaults();
  223. }
  224. void EnvelopeParams::ASRinit_bw(char A_val, char A_dt, char R_val, char R_dt)
  225. {
  226. setpresettype("Penvbandwidth");
  227. Envmode = 5;
  228. PA_val = A_val;
  229. PA_dt = A_dt;
  230. PR_val = R_val;
  231. PR_dt = R_dt;
  232. Pfreemode = 0;
  233. converttofree();
  234. store2defaults();
  235. }
  236. /*
  237. * Convert the Envelope to freemode
  238. */
  239. void EnvelopeParams::converttofree()
  240. {
  241. switch(Envmode) {
  242. case 1:
  243. Penvpoints = 4;
  244. Penvsustain = 2;
  245. Penvval[0] = 0;
  246. Penvdt[1] = PA_dt;
  247. Penvval[1] = 127;
  248. Penvdt[2] = PD_dt;
  249. Penvval[2] = PS_val;
  250. Penvdt[3] = PR_dt;
  251. Penvval[3] = 0;
  252. break;
  253. case 2:
  254. Penvpoints = 4;
  255. Penvsustain = 2;
  256. Penvval[0] = 0;
  257. Penvdt[1] = PA_dt;
  258. Penvval[1] = 127;
  259. Penvdt[2] = PD_dt;
  260. Penvval[2] = PS_val;
  261. Penvdt[3] = PR_dt;
  262. Penvval[3] = 0;
  263. break;
  264. case 3:
  265. Penvpoints = 3;
  266. Penvsustain = 1;
  267. Penvval[0] = PA_val;
  268. Penvdt[1] = PA_dt;
  269. Penvval[1] = 64;
  270. Penvdt[2] = PR_dt;
  271. Penvval[2] = PR_val;
  272. break;
  273. case 4:
  274. Penvpoints = 4;
  275. Penvsustain = 2;
  276. Penvval[0] = PA_val;
  277. Penvdt[1] = PA_dt;
  278. Penvval[1] = PD_val;
  279. Penvdt[2] = PD_dt;
  280. Penvval[2] = 64;
  281. Penvdt[3] = PR_dt;
  282. Penvval[3] = PR_val;
  283. break;
  284. case 5:
  285. Penvpoints = 3;
  286. Penvsustain = 1;
  287. Penvval[0] = PA_val;
  288. Penvdt[1] = PA_dt;
  289. Penvval[1] = 64;
  290. Penvdt[2] = PR_dt;
  291. Penvval[2] = PR_val;
  292. break;
  293. }
  294. }
  295. void EnvelopeParams::add2XML(XMLwrapper& xml)
  296. {
  297. xml.addparbool("free_mode", Pfreemode);
  298. xml.addpar("env_points", Penvpoints);
  299. xml.addpar("env_sustain", Penvsustain);
  300. xml.addpar("env_stretch", Penvstretch);
  301. xml.addparbool("forced_release", Pforcedrelease);
  302. xml.addparbool("linear_envelope", Plinearenvelope);
  303. xml.addpar("A_dt", PA_dt);
  304. xml.addpar("D_dt", PD_dt);
  305. xml.addpar("R_dt", PR_dt);
  306. xml.addpar("A_val", PA_val);
  307. xml.addpar("D_val", PD_val);
  308. xml.addpar("S_val", PS_val);
  309. xml.addpar("R_val", PR_val);
  310. if((Pfreemode != 0) || (!xml.minimal))
  311. for(int i = 0; i < Penvpoints; ++i) {
  312. xml.beginbranch("POINT", i);
  313. if(i != 0)
  314. xml.addpar("dt", Penvdt[i]);
  315. xml.addpar("val", Penvval[i]);
  316. xml.endbranch();
  317. }
  318. }
  319. void EnvelopeParams::getfromXML(XMLwrapper& xml)
  320. {
  321. Pfreemode = xml.getparbool("free_mode", Pfreemode);
  322. Penvpoints = xml.getpar127("env_points", Penvpoints);
  323. Penvsustain = xml.getpar127("env_sustain", Penvsustain);
  324. Penvstretch = xml.getpar127("env_stretch", Penvstretch);
  325. Pforcedrelease = xml.getparbool("forced_release", Pforcedrelease);
  326. Plinearenvelope = xml.getparbool("linear_envelope", Plinearenvelope);
  327. PA_dt = xml.getpar127("A_dt", PA_dt);
  328. PD_dt = xml.getpar127("D_dt", PD_dt);
  329. PR_dt = xml.getpar127("R_dt", PR_dt);
  330. PA_val = xml.getpar127("A_val", PA_val);
  331. PD_val = xml.getpar127("D_val", PD_val);
  332. PS_val = xml.getpar127("S_val", PS_val);
  333. PR_val = xml.getpar127("R_val", PR_val);
  334. for(int i = 0; i < Penvpoints; ++i) {
  335. if(xml.enterbranch("POINT", i) == 0)
  336. continue;
  337. if(i != 0)
  338. Penvdt[i] = xml.getpar127("dt", Penvdt[i]);
  339. Penvval[i] = xml.getpar127("val", Penvval[i]);
  340. xml.exitbranch();
  341. }
  342. if(!Pfreemode)
  343. converttofree();
  344. }
  345. void EnvelopeParams::defaults()
  346. {
  347. Penvstretch = Denvstretch;
  348. Pforcedrelease = Dforcedrelease;
  349. Plinearenvelope = Dlinearenvelope;
  350. PA_dt = DA_dt;
  351. PD_dt = DD_dt;
  352. PR_dt = DR_dt;
  353. PA_val = DA_val;
  354. PD_val = DD_val;
  355. PS_val = DS_val;
  356. PR_val = DR_val;
  357. Pfreemode = 0;
  358. converttofree();
  359. }
  360. void EnvelopeParams::store2defaults()
  361. {
  362. Denvstretch = Penvstretch;
  363. Dforcedrelease = Pforcedrelease;
  364. Dlinearenvelope = Plinearenvelope;
  365. DA_dt = PA_dt;
  366. DD_dt = PD_dt;
  367. DR_dt = PR_dt;
  368. DA_val = PA_val;
  369. DD_val = PD_val;
  370. DS_val = PS_val;
  371. DR_val = PR_val;
  372. }