EnvelopeParams.cpp (23543B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 EnvelopeParams.cpp - Parameters for Envelope 5 Copyright (C) 2002-2005 Nasca Octavian Paul 6 Author: Nasca Octavian Paul 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 */ 13 14 #include <cmath> 15 #include <cstdlib> 16 #include <cassert> 17 #include <rtosc/ports.h> 18 #include <rtosc/port-sugar.h> 19 20 #include "zyn-version.h" 21 #include "EnvelopeParams.h" 22 #include "../Misc/Util.h" 23 #include "../Misc/Time.h" 24 25 using namespace rtosc; 26 27 namespace zyn { 28 29 #define rObject EnvelopeParams 30 #define rBegin [](const char *msg, RtData &d) { \ 31 (void)* msg; EnvelopeParams *env = (rObject*) d.obj 32 #define rEnd } 33 34 #define dT127(var) limit( (int)roundf(log2f(var*100.0f + 1.0f) * 127.0f/12.0f), 0, 127 ) 35 #define dTREAL(var) (powf(2.0f, var / 127.0f * 12.0f) - 1.0f) / 100.0f 36 37 #define rParamDT(name, ...) \ 38 {"P" STRINGIFY(name) "::i", rProp(alias) rProp(parameter) DOC(__VA_ARGS__), NULL, rParamDTCb(name)} 39 40 #define rParamDTCb(name) rBOIL_BEGIN \ 41 if(!strcmp("", args)) {\ 42 data.reply(loc, "i", dT127(obj->name)); \ 43 } else { \ 44 unsigned char var = rtosc_argument(msg, 0).i; \ 45 rLIMIT(var, atoi) \ 46 rCAPPLY(obj->name, "f", obj->name = dTREAL(var)) \ 47 data.broadcast(loc, "i", dT127(obj->name));\ 48 rChangeCb \ 49 } rBOIL_END 50 51 #define rParamsDT(name, length, ...) \ 52 rArrayDT(name, length, __VA_ARGS__), \ 53 {"P" STRINGIFY(name) ":", rProp(alias) rDoc("get all data from aliased array"), NULL, rParamsDTCb(name, length)} 54 55 #define rParamsDTCb(name, length) rBOIL_BEGIN \ 56 char varS[length]; \ 57 for (int i = 0; i < length; i++) {varS[i] = dT127(obj->name[i]);} \ 58 data.reply(loc, "b", length, varS); rBOIL_END 59 60 #define rArrayDT(name, length, ...) \ 61 {"P" STRINGIFY(name) "#" STRINGIFY(length) "::i", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayDTICb(name)} 62 63 #define rArrayDTICb(name) rBOILS_BEGIN \ 64 if(!strcmp("", args)) {\ 65 data.reply(loc, "i", dT127(obj->name[idx])); \ 66 } else { \ 67 char varI = rtosc_argument(msg, 0).i; \ 68 float var = dTREAL(varI); \ 69 rLIMIT(var, atoi) \ 70 rAPPLY(name[idx], f) \ 71 data.broadcast(loc, "i", dT127(obj->name[idx]));\ 72 rChangeCb \ 73 } rBOILS_END 74 75 static const rtosc::Ports localPorts = { 76 rSelf(EnvelopeParams), 77 rPasteRt, 78 #undef rChangeCb 79 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); if (obj->time) { \ 80 obj->last_update_timestamp = obj->time->time(); } 81 rOption(loc, rProp(internal), 82 rOptions(ad_global_amp, ad_global_freq, ad_global_filter, 83 ad_voice_amp, ad_voice_freq, ad_voice_filter, 84 ad_voice_fm_amp, ad_voice_fm_freq, 85 sub_freq, sub_bandwidth), 86 "location of the envelope"), 87 rToggle(Pfreemode, rDefault(false), "Complex Envelope Definitions"), 88 #undef rChangeCb 89 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); \ 90 if(obj->time) { obj->last_update_timestamp = obj->time->time(); } 91 rParamZyn(Penvpoints, rProp(internal), rDefaultDepends(loc), 92 rPresetAtMulti(3, ad_global_freq, ad_voice_freq, 93 ad_voice_fm_freq, 94 sub_freq, sub_bandwidth), 95 rDepends(Pfreemode), 96 rDefault(4), 97 "Number of points in complex definition"), 98 rParamZyn(Penvsustain, rDefaultDepends(loc), 99 rPresetAtMulti(1, ad_global_freq, ad_voice_freq, 100 ad_voice_fm_freq, 101 sub_freq, sub_bandwidth), 102 rDepends(Pfreemode), 103 rDefault(2), 104 "Location of the sustain point"), 105 rParamZyn(Penvstretch, rShort("stretch"), rDefaultDepends(loc), 106 rPresetAtMulti(0, ad_global_freq, ad_global_filter, 107 ad_voice_freq, ad_voice_filter, ad_voice_fm_freq, 108 sub_filter), 109 rDefault(64), 110 "Stretch with respect to frequency"), 111 rToggle(Pforcedrelease, rShort("frcr"), rDefaultDepends(loc), 112 rPresetAtMulti(true, ad_global_amp, ad_global_filter, ad_voice_amp, 113 ad_voice_fm_amp, sub_filter), 114 rDefault(false), 115 "Force Envelope to fully evaluate"), 116 rToggle(Plinearenvelope, rShort("lin/log"), rDefault(false), 117 "Linear or Logarithmic Envelopes"), 118 rToggle(Prepeating, rShort("repeat"), rDefault(false), 119 "Repeat the Envelope"), 120 rParamDT(A_dt , rShort("a.dt"), rLinear(0,127), rDepends(Pfreemode), 121 "Attack Time"), 122 rParamF(A_dt, rShort("a.dt"), rLogWithLogmin(0.f,41.0f, 0.0001f), 123 rDefaultDepends(loc), rDepends(Pfreemode), 124 rPreset(ad_global_freq, 0.254f), rPreset(ad_global_filter, 0.127f), 125 rPreset(ad_voice_freq, 0.127f), rPreset(ad_voice_filter, 0.970f), 126 rPreset(ad_voice_fm_freq, 3.620f), rPreset(ad_voice_fm_amp, 1.876f), 127 rPreset(sub_freq, 0.254f), rPreset(sub_bandwidth, 0.970f), 128 rPreset(sub_filter, 0.13 (0x1.041894p-3)), 129 rDefault(0.0f), 130 "Attack Time"), 131 132 rParamZyn(PA_val, rShort("a.val"), 133 rDefaultDepends(loc), rDepends(Pfreemode), 134 rPreset(ad_voice_freq, 30), rPreset(ad_voice_filter, 90), 135 rPreset(ad_voice_fm_freq, 20), 136 rPreset(sub_freq, 30), rPreset(sub_bandwidth, 100), 137 rDefault(64), 138 "Attack Value"), 139 rParamDT(D_dt, rShort("d.dt"), rLinear(0,127), rDepends(Pfreemode), 140 "Decay Time"), 141 rParamF(D_dt, rShort("d.dt"), rLogWithLogmin(0.f, 41.0f, 0.0001f), 142 rDefaultDepends(loc), rDepends(Pfreemode), 143 rPreset(ad_global_amp, 0.127f), rPreset(ad_global_filter, 0.970f), 144 rPreset(ad_voice_amp, 6.978f), rPreset(ad_voice_filter, 0.970f), 145 rPreset(ad_voice_fm_amp, 3.620f), 146 rPreset(sub_filter, 0.97), 147 rDefault(0.009f), 148 "Decay Time"), 149 rParamZyn(PD_val, rShort("d.val"), 150 rDefaultDepends(loc), rDepends(Pfreemode), 151 rDefault(64), rPreset(ad_voice_filter, 40), 152 "Decay Value"), 153 rParamZyn(PS_val, rShort("s.val"), 154 rDefaultDepends(loc), rDepends(Pfreemode), rDefault(64), 155 rPresetAtMulti(127, ad_global_amp, ad_voice_amp, ad_voice_fm_amp), 156 "Sustain Value"), 157 rParamDT(R_dt, rShort("r.dt"), rLinear(0,127), rDepends(Pfreemode), 158 "Release Time"), 159 rParamF(R_dt, rShort("r.dt"), rLogWithLogmin(0.f,41.0f,0.009f), 160 rDefaultDepends(loc), rDepends(Pfreemode), 161 rPreset(ad_global_amp, 0.041f), 162 rPreset(ad_voice_amp, 6.978f), rPreset(ad_voice_filter, 0.009f), 163 rPreset(ad_voice_fm_freq, 1.876f), rPreset(ad_voice_fm_amp, 6.978f), 164 rDefault(0.499f), 165 "Release Time"), 166 rParamZyn(PR_val, rShort("r.val"), 167 rDefaultDepends(loc), rDepends(Pfreemode), 168 rPresetAtMulti(40, ad_voice_filter, ad_voice_fm_freq), 169 rDefault(64), 170 "Release Value"), 171 #undef rChangeCb 172 #define rChangeCb if(!obj->Pfreemode) obj->converttofree(); \ 173 if(obj->time) { obj->last_update_timestamp = obj->time->time(); } \ 174 if(idx >= obj->Penvpoints) { obj->Penvpoints = idx + 1; } 175 rParamsDT(envdt, MAX_ENVELOPE_POINTS, rProp(alias), "Envelope Delay Times"), 176 rArrayF(envdt, MAX_ENVELOPE_POINTS, rProp(parameter), 177 rEnabledBy(Pfreemode), 178 rDefault([0.0 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 179 rPreset(ad_voice_freq, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 180 rPreset(ad_voice_amp, [0.00 (0x0p+0) 0.00 (0x0p+0) 6.98 (0x1.be978ep+2) 6.98 (0x1.be978ep+2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 181 rPreset(ad_voice_filter, [0.00 (0x0p+0) 0.97 (0x1.f0a3d8p-1) 0.97 (0x1.f0a3d8p-1) 0.01 (0x1.26e978p-7) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 182 rPreset(ad_voice_fm_freq, [0.00 (0x0p+0) 3.62 (0x1.cf5c28p+1) 1.88 (0x1.e0418ap+0) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 183 rPreset(ad_voice_fm_amp, [0.00 (0x0p+0) 1.88 (0x1.e0418ap+0) 3.62 (0x1.cf5c28p+1) 6.98 (0x1.be978ep+2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 184 rPreset(ad_global_freq, [0.00 (0x0p+0) 0.25 (0x1.041894p-2) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 185 rPreset(ad_global_amp, [0.00 (0x0p+0) 0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.04 (0x1.4fdf3cp-5) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 186 rPreset(ad_global_filter, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 187 rPreset(sub_freq, [0.00 (0x0p+0) 0.25 (0x1.041894p-2) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 188 rPreset(sub_bandwidth, [0.00 (0x0p+0) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 189 rPreset(sub_filter, [0.00 (0x0p+0) 0.13 (0x1.041894p-3) 0.97 (0x1.f0a3d8p-1) 0.50 (0x1.fef9dcp-2) 0.07 (0x1.242124p-4) 0.07 (0x1.242124p-4) ...]), 190 rDefaultDepends(loc), rDepends(Pfreemode,A_dt,D_dt,R_dt), 191 "Envelope Delay Times (ms)"), 192 rParams(Penvval, MAX_ENVELOPE_POINTS, 193 rEnabledBy(Pfreemode), 194 rDefault([64 64 ...]), 195 rPreset(ad_global_amp, [0 127 127 0 64 64 ...]), 196 rPreset(ad_voice_amp, [0 127 127 0 64 64 ...]), 197 rPreset(ad_voice_fm_amp, [0 127 127 0 64 64 ...]), 198 rPreset(ad_voice_fm_freq, [20 64 40 64 64 ...]), 199 rPreset(ad_voice_freq, [30 64 64 ...]), 200 rPreset(ad_voice_filter, [90 40 64 40 64 64 ...]), 201 rPreset(sub_bandwidth, [100 64 64 ...]), 202 rPreset(sub_freq, [30 64 64 ...]), 203 rDefaultDepends(loc) rDepends(Penvpoints,Pfreemode,PA_val,PD_val,PS_val,PR_val), "Envelope Values"), 204 #undef rChangeCb 205 {"Envmode:", rDoc("Envelope variant type"), NULL, 206 rBegin; 207 d.reply(d.loc, "i", env->Envmode); 208 rEnd}, 209 {"envdt", rDoc("Envelope Delay Times (ms)"), NULL, 210 rBegin; 211 const int N = MAX_ENVELOPE_POINTS; 212 const int M = rtosc_narguments(msg); 213 if(M == 0) { 214 rtosc_arg_t args[N]; 215 char arg_types[N+1] = {0}; 216 for(int i=0; i<N; ++i) { 217 args[i].f = env->getdt(i)*1000; //answer milliseconds to old gui 218 arg_types[i] = 'f'; 219 } 220 d.replyArray(d.loc, arg_types, args); 221 } else { 222 for(int i=0; i<N && i<M; ++i) { 223 env->envdt[i] = (rtosc_argument(msg, i).f)/1000; //store as seconds in member variable 224 } 225 } 226 rEnd}, 227 {"dt", rDoc("Envelope Delay Times (sec)"), NULL, 228 rBegin; 229 230 const int N = MAX_ENVELOPE_POINTS; 231 const int M = rtosc_narguments(msg); 232 if(M == 0) { 233 rtosc_arg_t args[N]; 234 char arg_types[N+1] = {}; 235 for(int i=0; i<N; ++i) { 236 args[i].f = env->getdt(i); 237 arg_types[i] = 'f'; 238 } 239 d.replyArray(d.loc, arg_types, args); 240 } else { 241 for(int i=0; i<N && i<M; ++i) 242 env->envdt[i] = (rtosc_argument(msg, i).f); 243 } 244 rEnd}, 245 {"envval", rDoc("Envelope Values"), NULL, 246 rBegin; 247 const int N = MAX_ENVELOPE_POINTS; 248 const int M = rtosc_narguments(msg); 249 if(M == 0) { 250 rtosc_arg_t args[N]; 251 char arg_types[N+1] = {}; 252 for(int i=0; i<N; ++i) { 253 args[i].f = env->Penvval[i]/127.0f; 254 arg_types[i] = 'f'; 255 } 256 d.replyArray(d.loc, arg_types, args); 257 } else { 258 for(int i=0; i<N && i<M; ++i) { 259 env->Penvval[i] = limit(roundf(rtosc_argument(msg,i).f*127.0f), 0.0f, 127.0f); 260 } 261 } 262 rEnd}, 263 264 {"addPoint:i", rProp(internal) rDoc("Add point to envelope"), NULL, 265 rBegin; 266 const int curpoint = rtosc_argument(msg, 0).i; 267 //int curpoint=freeedit->lastpoint; 268 if (curpoint<0 || curpoint>env->Penvpoints || env->Penvpoints>=MAX_ENVELOPE_POINTS) 269 return; 270 271 for (int i=env->Penvpoints; i>=curpoint+1; i--) { 272 env->envdt[i]=env->envdt[i-1]; 273 env->Penvval[i]=env->Penvval[i-1]; 274 } 275 276 if (curpoint==0) 277 env->envdt[1]=dTREAL(64); 278 279 env->Penvpoints++; 280 if (curpoint<=env->Penvsustain) 281 env->Penvsustain++; 282 rEnd}, 283 {"delPoint:i", rProp(internal) rDoc("Delete Envelope Point"), NULL, 284 rBegin; 285 const int curpoint=rtosc_argument(msg, 0).i; 286 if(curpoint<1 || curpoint>=env->Penvpoints-1 || env->Penvpoints<=3) 287 return; 288 289 for (int i=curpoint+1;i<env->Penvpoints;i++){ 290 env->envdt[i-1]=env->envdt[i]; 291 env->Penvval[i-1]=env->Penvval[i]; 292 }; 293 294 env->Penvpoints--; 295 296 if (curpoint<=env->Penvsustain) 297 env->Penvsustain--; 298 299 rEnd}, 300 }; 301 302 const rtosc::Ports &EnvelopeParams::ports = localPorts; 303 304 305 EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_, 306 unsigned char Pforcedrelease_, 307 const AbsTime *time_): 308 time(time_), last_update_timestamp(0) 309 { 310 A_dt = 0.009; 311 D_dt = 0.009; 312 R_dt = 0.009; 313 PA_val = 64; 314 PD_val = 64; 315 PS_val = 64; 316 PR_val = 64; 317 318 for(int i = 0; i < MAX_ENVELOPE_POINTS; ++i) { 319 envdt[i] = dTREAL(32); 320 Penvval[i] = 64; 321 } 322 envdt[0] = 0.0f; //not used 323 Penvsustain = 1; 324 Penvpoints = 1; 325 Envmode = ADSR_lin; 326 Penvstretch = Penvstretch_; 327 Pforcedrelease = Pforcedrelease_; 328 Pfreemode = 1; 329 Plinearenvelope = 0; 330 Prepeating = 0; 331 332 store2defaults(); 333 } 334 335 EnvelopeParams::~EnvelopeParams() 336 {} 337 338 #define COPY(y) this->y = ep.y 339 void EnvelopeParams::paste(const EnvelopeParams &ep) 340 { 341 342 COPY(Pfreemode); 343 COPY(Penvpoints); 344 COPY(Penvsustain); 345 for(int i=0; i<MAX_ENVELOPE_POINTS; ++i) { 346 this->envdt[i] = ep.envdt[i]; 347 this->Penvval[i] = ep.Penvval[i]; 348 } 349 COPY(Penvstretch); 350 COPY(Pforcedrelease); 351 COPY(Plinearenvelope); 352 353 COPY(A_dt); 354 COPY(D_dt); 355 COPY(R_dt); 356 COPY(PA_val); 357 COPY(PD_val); 358 COPY(PS_val); 359 COPY(PR_val); 360 361 if ( time ) { 362 last_update_timestamp = time->time(); 363 } 364 } 365 #undef COPY 366 367 void EnvelopeParams::init(zyn::consumer_location_t _loc) 368 { 369 switch(loc = _loc) 370 { 371 case ad_global_amp: ADSRinit_dB(0.0f, 0.127f, 127, 0.041f); break; 372 case ad_global_freq: ASRinit(64, 0.254f, 64, 0.499f); break; 373 case ad_global_filter: 374 case sub_filter: ADSRinit_filter(64, 0.127f, 64, 0.970f, 0.499f, 64); break; 375 case ad_voice_amp: ADSRinit_dB(0.0f, 6.978f, 127, 6.978f); break; 376 case ad_voice_freq: ASRinit(30, 0.127f, 64, 0.499f); break; 377 case ad_voice_filter: ADSRinit_filter(90, 0.970f, 40, 0.970f, 0.009f, 40); break; 378 case ad_voice_fm_freq: ASRinit(20, 3.620f, 40, 1.876f); break; 379 case ad_voice_fm_amp: ADSRinit(1.876f, 3.620f, 127, 6.978f); break; 380 case sub_freq: ASRinit(30, 0.254f, 64, 0.499f); break; 381 case sub_bandwidth: ASRinit_bw(100, 0.970f, 64, 0.499f); break; 382 default: throw std::logic_error("Invalid envelope consumer location"); 383 }; 384 } 385 386 float EnvelopeParams::getdt(char i) const 387 { 388 return envdt[(int)i]; //seconds 389 } 390 391 /* 392 * ADSR/ASR... initialisations 393 */ 394 void EnvelopeParams::ADSRinit(float a_dt, float d_dt, char s_val, float r_dt) 395 { 396 setpresettype("Penvamplitude"); 397 Envmode = ADSR_lin; 398 A_dt = a_dt; 399 D_dt = d_dt; 400 PS_val = s_val; 401 R_dt = r_dt; 402 Pfreemode = 0; 403 converttofree(); 404 405 store2defaults(); 406 } 407 408 void EnvelopeParams::ADSRinit_dB(float a_dt, float d_dt, char s_val, float r_dt) 409 { 410 setpresettype("Penvamplitude"); 411 Envmode = ADSR_dB; 412 A_dt = a_dt; 413 D_dt = d_dt; 414 PS_val = s_val; 415 R_dt = r_dt; 416 Pfreemode = 0; 417 converttofree(); 418 419 store2defaults(); 420 } 421 422 void EnvelopeParams::ASRinit(char a_val, float a_dt, char r_val, float r_dt) 423 { 424 setpresettype("Penvfrequency"); 425 Envmode = ASR_freqlfo; 426 PA_val = a_val; 427 A_dt = a_dt; 428 PR_val = r_val; 429 R_dt = r_dt; 430 Pfreemode = 0; 431 converttofree(); 432 433 store2defaults(); 434 } 435 436 void EnvelopeParams::ADSRinit_filter(char a_val, 437 float a_dt, 438 char d_val, 439 float d_dt, 440 float r_dt, 441 char r_val) 442 { 443 setpresettype("Penvfilter"); 444 Envmode = ADSR_filter; 445 PA_val = a_val; 446 A_dt = a_dt; 447 PD_val = d_val; 448 D_dt = d_dt; 449 R_dt = r_dt; 450 PR_val = r_val; 451 Pfreemode = 0; 452 converttofree(); 453 store2defaults(); 454 } 455 456 void EnvelopeParams::ASRinit_bw(char a_val, float a_dt, char r_val, float r_dt) 457 { 458 setpresettype("Penvbandwidth"); 459 Envmode = ASR_bw; 460 PA_val = a_val; 461 A_dt = a_dt; 462 PR_val = r_val; 463 R_dt = r_dt; 464 Pfreemode = 0; 465 converttofree(); 466 store2defaults(); 467 } 468 469 /* 470 * Convert the Envelope to freemode 471 */ 472 void EnvelopeParams::converttofree() 473 { 474 switch(Envmode) { 475 case ADSR_lin: 476 case ADSR_dB: 477 Penvpoints = 4; 478 Penvsustain = 2; 479 Penvval[0] = 0; 480 envdt[1] = A_dt; 481 Penvval[1] = 127; 482 envdt[2] = D_dt; 483 Penvval[2] = PS_val; 484 envdt[3] = R_dt; 485 Penvval[3] = 0; 486 break; 487 case ASR_freqlfo: 488 case ASR_bw: 489 Penvpoints = 3; 490 Penvsustain = 1; 491 Penvval[0] = PA_val; 492 envdt[1] = A_dt; 493 Penvval[1] = 64; 494 envdt[2] = R_dt; 495 Penvval[2] = PR_val; 496 break; 497 case ADSR_filter: 498 Penvpoints = 4; 499 Penvsustain = 2; 500 Penvval[0] = PA_val; 501 envdt[1] = A_dt; 502 Penvval[1] = PD_val; 503 envdt[2] = D_dt; 504 Penvval[2] = 64; 505 envdt[3] = R_dt; 506 Penvval[3] = PR_val; 507 break; 508 } 509 } 510 511 512 513 514 void EnvelopeParams::add2XML(XMLwrapper& xml) 515 { 516 xml.addparbool("free_mode", Pfreemode); 517 xml.addpar("env_points", Penvpoints); 518 xml.addpar("env_sustain", Penvsustain); 519 xml.addpar("env_stretch", Penvstretch); 520 xml.addparbool("forced_release", Pforcedrelease); 521 xml.addparbool("linear_envelope", Plinearenvelope); 522 xml.addparbool("repeating_envelope", Prepeating); 523 xml.addparreal("A_dt", A_dt); 524 xml.addparreal("D_dt", D_dt); 525 xml.addparreal("R_dt", R_dt); 526 xml.addpar("A_val", PA_val); 527 xml.addpar("D_val", PD_val); 528 xml.addpar("S_val", PS_val); 529 xml.addpar("R_val", PR_val); 530 531 if((Pfreemode != 0) || (!xml.minimal)) 532 for(int i = 0; i < Penvpoints; ++i) { 533 xml.beginbranch("POINT", i); 534 if(i != 0) 535 xml.addparreal("dt", envdt[i]); 536 xml.addpar("val", Penvval[i]); 537 xml.endbranch(); 538 } 539 } 540 541 float EnvelopeParams::env_dB2rap(float db) { 542 return (powf(10.0f, db / 20.0f) - 0.01)/.99f; 543 } 544 545 float EnvelopeParams::env_rap2dB(float rap) { 546 return 20.0f * log10f(rap * 0.99f + 0.01); 547 } 548 549 /** 550 since commit 5334d94283a513ae42e472aa020db571a3589fb9, i.e. between 551 versions 2.4.3 and 2.4.4, the amplitude envelope has been converted 552 differently from dB to rap for AmplitudeEnvelope (mode 2) 553 this converts the values read from an XML file once 554 */ 555 struct version_fixer_t 556 { 557 const bool mismatch; 558 public: 559 int operator()(int input) const 560 { 561 return (mismatch) 562 // The errors occurred when calling env_dB2rap. Let f be the 563 // conversion function for mode 2 (see Envelope.cpp), then we 564 // load values with (let "o" be the function composition symbol): 565 // f^{-1} o (env_dB2rap^{-1}) o dB2rap o f 566 // from the xml file. This results in the following formula: 567 ? roundf(127.0f * (0.5f * 568 log10f( 0.01f + 0.99f * 569 powf(100, input/127.0f - 1)) 570 + 1)) 571 : input; 572 } 573 version_fixer_t(const version_type& fileversion, int env_mode) : 574 mismatch(fileversion < version_type(2,4,4) && 575 (env_mode == 2)) {} 576 }; 577 578 void EnvelopeParams::getfromXML(XMLwrapper& xml) 579 { 580 Pfreemode = xml.getparbool("free_mode", Pfreemode); 581 Penvpoints = xml.getpar127("env_points", Penvpoints); 582 Penvsustain = xml.getpar127("env_sustain", Penvsustain); 583 Penvstretch = xml.getpar127("env_stretch", Penvstretch); 584 Pforcedrelease = xml.getparbool("forced_release", Pforcedrelease); 585 Plinearenvelope = xml.getparbool("linear_envelope", Plinearenvelope); 586 Prepeating = xml.getparbool("repeating_envelope", Prepeating); 587 588 version_fixer_t version_fix(xml.fileversion(), Envmode); 589 590 if(!xml.hasparreal("A_dt")) { 591 A_dt = dTREAL(xml.getpar127("A_dt", 0)); 592 D_dt = dTREAL(xml.getpar127("D_dt", 0)); 593 R_dt = dTREAL(xml.getpar127("R_dt", 0)); 594 } else { 595 A_dt = xml.getparreal("A_dt", A_dt); 596 D_dt = xml.getparreal("D_dt", D_dt); 597 R_dt = xml.getparreal("R_dt", R_dt); 598 } 599 600 PA_val = version_fix(xml.getpar127("A_val", PA_val)); 601 PD_val = version_fix(xml.getpar127("D_val", PD_val)); 602 PS_val = version_fix(xml.getpar127("S_val", PS_val)); 603 PR_val = version_fix(xml.getpar127("R_val", PR_val)); 604 605 for(int i = 0; i < Penvpoints; ++i) { 606 if(xml.enterbranch("POINT", i) == 0) 607 continue; 608 if(i != 0) { 609 if(!xml.hasparreal("dt")) { 610 int dt = xml.getpar127("dt", dT127(envdt[i])); 611 envdt[i] = dTREAL(dt); 612 } 613 else { 614 envdt[i] = xml.getparreal("dt", envdt[i]); 615 } 616 } 617 Penvval[i] = version_fix(xml.getpar127("val", Penvval[i])); 618 xml.exitbranch(); 619 } 620 621 if(!Pfreemode) 622 converttofree(); 623 } 624 625 626 void EnvelopeParams::defaults() 627 { 628 Penvstretch = Denvstretch; 629 Pforcedrelease = Dforcedrelease; 630 Plinearenvelope = Dlinearenvelope; 631 Prepeating = Drepeating; 632 A_dt = DA_dt; 633 D_dt = DD_dt; 634 R_dt = DR_dt; 635 PA_val = DA_val; 636 PD_val = DD_val; 637 PS_val = DS_val; 638 PR_val = DR_val; 639 Pfreemode = 0; 640 converttofree(); 641 } 642 643 void EnvelopeParams::store2defaults() 644 { 645 Denvstretch = Penvstretch; 646 Dforcedrelease = Pforcedrelease; 647 Dlinearenvelope = Plinearenvelope; 648 Drepeating = Prepeating; 649 DA_dt = A_dt; 650 DD_dt = D_dt; 651 DR_dt = R_dt; 652 DA_val = PA_val; 653 DD_val = PD_val; 654 DS_val = PS_val; 655 DR_val = PR_val; 656 } 657 658 }