comparison src/Input/sexypsf/spu/adsr.c @ 0:13389e613d67 trunk

[svn] - initial import of audacious-plugins tree (lots to do)
author nenolod
date Mon, 18 Sep 2006 01:11:49 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13389e613d67
1 /***************************************************************************
2 adsr.c - description
3 -------------------
4 begin : Wed May 15 2002
5 copyright : (C) 2002 by Pete Bernert
6 email : BlackDove@addcom.de
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. See also the license.txt file for *
15 * additional informations. *
16 * *
17 ***************************************************************************/
18
19 //*************************************************************************//
20 // History of changes:
21 //
22 // 2003/01/06 - Pete
23 // - added Neill's ADSR timings
24 //
25 // 2002/05/15 - Pete
26 // - generic cleanup for the Peops release
27 //
28 //*************************************************************************//
29
30 #define _IN_ADSR
31
32 // will be included from spu.c
33 #ifdef _IN_SPU
34
35 ////////////////////////////////////////////////////////////////////////
36 // ADSR func
37 ////////////////////////////////////////////////////////////////////////
38
39 static u32 RateTable[160];
40
41 static void InitADSR(void) // INIT ADSR
42 {
43 u32 r,rs,rd;int i;
44
45 memset(RateTable,0,sizeof(u32)*160); // build the rate table according to Neill's rules (see at bottom of file)
46
47 r=3;rs=1;rd=0;
48
49 for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0
50 {
51 if(r<0x3FFFFFFF)
52 {
53 r+=rs;
54 rd++;if(rd==5) {rd=1;rs*=2;}
55 }
56 if(r>0x3FFFFFFF) r=0x3FFFFFFF;
57
58 RateTable[i]=r;
59 }
60 }
61
62 ////////////////////////////////////////////////////////////////////////
63
64 static INLINE void StartADSR(int ch) // MIX ADSR
65 {
66 s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
67 s_chan[ch].ADSRX.State=0;
68 s_chan[ch].ADSRX.EnvelopeVol=0;
69 }
70
71 ////////////////////////////////////////////////////////////////////////
72
73 static INLINE int MixADSR(int ch) // MIX ADSR
74 {
75 static const int sexytable[8]=
76 {0,4,6,8,9,10,11,12};
77
78 if(s_chan[ch].bStop) // should be stopped:
79 { // do release
80 if(s_chan[ch].ADSRX.ReleaseModeExp)
81 {
82 s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
83 }
84 else
85 {
86 s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
87 }
88
89 if(s_chan[ch].ADSRX.EnvelopeVol<0)
90 {
91 s_chan[ch].ADSRX.EnvelopeVol=0;
92 s_chan[ch].bOn=0;
93 s_chan[ch].bNoise=0;
94 }
95
96 s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
97 return s_chan[ch].ADSRX.lVolume;
98 }
99 else // not stopped yet?
100 {
101 if(s_chan[ch].ADSRX.State==0) // -> attack
102 {
103 if(s_chan[ch].ADSRX.AttackModeExp)
104 {
105 if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
106 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
107 else
108 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
109 }
110 else
111 {
112 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
113 }
114
115 if(s_chan[ch].ADSRX.EnvelopeVol<0)
116 {
117 s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
118 s_chan[ch].ADSRX.State=1;
119 }
120
121 s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
122 return s_chan[ch].ADSRX.lVolume;
123 }
124 //--------------------------------------------------//
125 if(s_chan[ch].ADSRX.State==1) // -> decay
126 {
127 s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
128
129 if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
130 if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
131 {
132 s_chan[ch].ADSRX.State=2;
133 }
134
135 s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
136 return s_chan[ch].ADSRX.lVolume;
137 }
138 //--------------------------------------------------//
139 if(s_chan[ch].ADSRX.State==2) // -> sustain
140 {
141 if(s_chan[ch].ADSRX.SustainIncrease)
142 {
143 if(s_chan[ch].ADSRX.SustainModeExp)
144 {
145 if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
146 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
147 else
148 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
149 }
150 else
151 {
152 s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
153 }
154
155 if(s_chan[ch].ADSRX.EnvelopeVol<0)
156 {
157 s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
158 }
159 }
160 else
161 {
162 if(s_chan[ch].ADSRX.SustainModeExp)
163 s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
164 else
165 s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
166
167 if(s_chan[ch].ADSRX.EnvelopeVol<0)
168 {
169 s_chan[ch].ADSRX.EnvelopeVol=0;
170 }
171 }
172 s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
173 return s_chan[ch].ADSRX.lVolume;
174 }
175 }
176 return 0;
177 }
178
179 #endif
180
181 /*
182 James Higgs ADSR investigations:
183
184 PSX SPU Envelope Timings
185 ~~~~~~~~~~~~~~~~~~~~~~~~
186
187 First, here is an extract from doomed's SPU doc, which explains the basics
188 of the SPU "volume envelope":
189
190 *** doomed doc extract start ***
191
192 --------------------------------------------------------------------------
193 Voices.
194 --------------------------------------------------------------------------
195 The SPU has 24 hardware voices. These voices can be used to reproduce sample
196 data, noise or can be used as frequency modulator on the next voice.
197 Each voice has it's own programmable ADSR envelope filter. The main volume
198 can be programmed independently for left and right output.
199
200 The ADSR envelope filter works as follows:
201 Ar = Attack rate, which specifies the speed at which the volume increases
202 from zero to it's maximum value, as soon as the note on is given. The
203 slope can be set to lineair or exponential.
204 Dr = Decay rate specifies the speed at which the volume decreases to the
205 sustain level. Decay is always decreasing exponentially.
206 Sl = Sustain level, base level from which sustain starts.
207 Sr = Sustain rate is the rate at which the volume of the sustained note
208 increases or decreases. This can be either lineair or exponential.
209 Rr = Release rate is the rate at which the volume of the note decreases
210 as soon as the note off is given.
211
212 lvl |
213 ^ | /\Dr __
214 Sl _| _ / _ \__--- \
215 | / ---__ \ Rr
216 | /Ar Sr \ \
217 | / \\
218 |/___________________\________
219 ->time
220
221 The overal volume can also be set to sweep up or down lineairly or
222 exponentially from it's current value. This can be done seperately
223 for left and right.
224
225 Relevant SPU registers:
226 -------------------------------------------------------------
227 $1f801xx8 Attack/Decay/Sustain level
228 bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
229 desc.|Am| Ar |Dr |Sl |
230
231 Am 0 Attack mode Linear
232 1 Exponential
233
234 Ar 0-7f attack rate
235 Dr 0-f decay rate
236 Sl 0-f sustain level
237 -------------------------------------------------------------
238 $1f801xxa Sustain rate, Release Rate.
239 bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
240 desc.|Sm|Sd| 0| Sr |Rm|Rr |
241
242 Sm 0 sustain rate mode linear
243 1 exponential
244 Sd 0 sustain rate mode increase
245 1 decrease
246 Sr 0-7f Sustain Rate
247 Rm 0 Linear decrease
248 1 Exponential decrease
249 Rr 0-1f Release Rate
250
251 Note: decay mode is always Expontial decrease, and thus cannot
252 be set.
253 -------------------------------------------------------------
254 $1f801xxc Current ADSR volume
255 bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
256 desc.|ADSRvol |
257
258 ADSRvol Returns the current envelope volume when
259 read.
260 -- James' Note: return range: 0 -> 32767
261
262 *** doomed doc extract end ***
263
264 By using a small PSX proggie to visualise the envelope as it was played,
265 the following results for envelope timing were obtained:
266
267 1. Attack rate value (linear mode)
268
269 Attack value range: 0 -> 127
270
271 Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 |
272 -----------------------------------------------------------------
273 Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890|
274
275 Note: frames is no. of PAL frames to reach full volume (100%
276 amplitude)
277
278 Hmm, noticing that the time taken to reach full volume doubles
279 every time we add 4 to our attack value, we know the equation is
280 of form:
281 frames = k * 2 ^ (value / 4)
282
283 (You may ponder about envelope generator hardware at this point,
284 or maybe not... :)
285
286 By substituting some stuff and running some checks, we get:
287
288 k = 0.00257 (close enuf)
289
290 therefore,
291 frames = 0.00257 * 2 ^ (value / 4)
292 If you just happen to be writing an emulator, then you can probably
293 use an equation like:
294
295 %volume_increase_per_tick = 1 / frames
296
297
298 ------------------------------------
299 Pete:
300 ms=((1<<(value>>2))*514)/10000
301 ------------------------------------
302
303 2. Decay rate value (only has log mode)
304
305 Decay value range: 0 -> 15
306
307 Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
308 ------------------------------------------------
309 frames | | | | | 6 | 12 | 24 | 47 |
310
311 Note: frames here is no. of PAL frames to decay to 50% volume.
312
313 formula: frames = k * 2 ^ (value)
314
315 Substituting, we get: k = 0.00146
316
317 Further info on logarithmic nature:
318 frames to decay to sustain level 3 = 3 * frames to decay to
319 sustain level 9
320
321 Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
322 50% volume.
323
324 Frag it - just use linear approx.
325
326 ------------------------------------
327 Pete:
328 ms=((1<<value)*292)/10000
329 ------------------------------------
330
331
332 3. Sustain rate value (linear mode)
333
334 Sustain rate range: 0 -> 127
335
336 Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
337 -------------------------------------------
338 frames | 9 | 19 | 37 | 74 | 147| 293| 587|
339
340 Here, frames = no. of PAL frames for volume amplitude to go from 100%
341 to 0% (or vice-versa).
342
343 Same formula as for attack value, just a different value for k:
344
345 k = 0.00225
346
347 ie: frames = 0.00225 * 2 ^ (value / 4)
348
349 For emulation purposes:
350
351 %volume_increase_or_decrease_per_tick = 1 / frames
352
353 ------------------------------------
354 Pete:
355 ms=((1<<(value>>2))*450)/10000
356 ------------------------------------
357
358
359 4. Release rate (linear mode)
360
361 Release rate range: 0 -> 31
362
363 Value | 13 | 14 | 15 | 16 | 17 |
364 ---------------------------------------------------------------
365 frames | 18 | 36 | 73 | 146| 292|
366
367 Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
368 after "note-off" is triggered.
369
370 Formula: frames = k * 2 ^ (value)
371
372 And so: k = 0.00223
373
374 ------------------------------------
375 Pete:
376 ms=((1<<value)*446)/10000
377 ------------------------------------
378
379
380 Other notes:
381
382 Log stuff not figured out. You may get some clues from the "Decay rate"
383 stuff above. For emu purposes it may not be important - use linear
384 approx.
385
386 To get timings in millisecs, multiply frames by 20.
387
388
389
390 - James Higgs 17/6/2000
391 james7780@yahoo.com
392
393 //---------------------------------------------------------------
394
395 OLD adsr mixing according to james' rules... has to be called
396 every one millisecond
397
398
399 i32 v,v2,lT,l1,l2,l3;
400
401 if(s_chan[ch].bStop) // psx wants to stop? -> release phase
402 {
403 if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now)
404 {
405 if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff
406 {
407 s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
408 s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
409 s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level
410 (s_chan[ch].ADSR.ReleaseTime*
411 s_chan[ch].ADSR.ReleaseVol)/1024;
412 }
413 // -> NO release exp mode used (yet)
414 v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume
415 lT=s_chan[ch].ADSR.lTime- // -> how much time is past?
416 s_chan[ch].ADSR.ReleaseStartTime;
417 l1=s_chan[ch].ADSR.ReleaseTime;
418
419 if(lT<l1) // -> we still have to release
420 {
421 v=v-((v*lT)/l1); // --> calc new volume
422 }
423 else // -> release is over: now really stop that sample
424 {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
425 }
426 else // -> release IS 0: release at once
427 {
428 v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
429 }
430 }
431 else
432 {//--------------------------------------------------// not in release phase:
433 v=1024;
434 lT=s_chan[ch].ADSR.lTime;
435 l1=s_chan[ch].ADSR.AttackTime;
436
437 if(lT<l1) // attack
438 { // no exp mode used (yet)
439 // if(s_chan[ch].ADSR.AttackModeExp)
440 // {
441 // v=(v*lT)/l1;
442 // }
443 // else
444 {
445 v=(v*lT)/l1;
446 }
447 if(v==0) v=1;
448 }
449 else // decay
450 { // should be exp, but who cares? ;)
451 l2=s_chan[ch].ADSR.DecayTime;
452 v2=s_chan[ch].ADSR.SustainLevel;
453
454 lT-=l1;
455 if(lT<l2)
456 {
457 v-=(((v-v2)*lT)/l2);
458 }
459 else // sustain
460 { // no exp mode used (yet)
461 l3=s_chan[ch].ADSR.SustainTime;
462 lT-=l2;
463 if(s_chan[ch].ADSR.SustainModeDec>0)
464 {
465 if(l3!=0) v2+=((v-v2)*lT)/l3;
466 else v2=v;
467 }
468 else
469 {
470 if(l3!=0) v2-=(v2*lT)/l3;
471 else v2=v;
472 }
473
474 if(v2>v) v2=v;
475 if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
476
477 v=v2;
478 }
479 }
480 }
481
482 //----------------------------------------------------//
483 // ok, done for this channel, so increase time
484
485 s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms;
486
487 if(v>1024) v=1024; // adjust volume
488 if(v<0) v=0;
489 s_chan[ch].ADSR.lVolume=v; // store act volume
490
491 return v; // return the volume factor
492 */
493
494
495 //-----------------------------------------------------------------------------
496 //-----------------------------------------------------------------------------
497 //-----------------------------------------------------------------------------
498
499
500 /*
501 -----------------------------------------------------------------------------
502 Neill Corlett
503 Playstation SPU envelope timing notes
504 -----------------------------------------------------------------------------
505
506 This is preliminary. This may be wrong. But the model described herein fits
507 all of my experimental data, and it's just simple enough to sound right.
508
509 ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
510 The value returned by channel reg 0xC is (envelope_level>>16).
511
512 Each sample, an increment or decrement value will be added to or
513 subtracted from this envelope level.
514
515 Create the rate log table. The values double every 4 entries.
516 entry #0 = 4
517
518 4, 5, 6, 7,
519 8,10,12,14,
520 16,20,24,28, ...
521
522 entry #40 = 4096...
523 entry #44 = 8192...
524 entry #48 = 16384...
525 entry #52 = 32768...
526 entry #56 = 65536...
527
528 increments and decrements are in terms of ratelogtable[n]
529 n may exceed the table bounds (plan on n being between -32 and 127).
530 table values are all clipped between 0x00000000 and 0x3FFFFFFF
531
532 when you "voice on", the envelope is always fully reset.
533 (yes, it may click. the real thing does this too.)
534
535 envelope level begins at zero.
536
537 each state happens for at least 1 cycle
538 (transitions are not instantaneous)
539 this may result in some oddness: if the decay rate is uberfast, it will cut
540 the envelope from full down to half in one sample, potentially skipping over
541 the sustain level
542
543 ATTACK
544 ------
545 - if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
546 proceed to DECAY.
547
548 Linear attack mode:
549 - line extends upward to 0x7FFFFFFF
550 - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
551
552 Logarithmic attack mode:
553 if envelope_level < 0x60000000:
554 - line extends upward to 0x60000000
555 - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
556 else:
557 - line extends upward to 0x7FFFFFFF
558 - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
559
560 DECAY
561 -----
562 - if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
563 Do not clip to the sustain level.
564 - current line ends at (envelope_level & 0x07FFFFFF)
565 - decrement per sample depends on (envelope_level>>28)&0x7
566 0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
567 1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
568 2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
569 3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
570 4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
571 5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
572 6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
573 7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
574 (note that this is the same as the release rate formula, except that
575 decay rates 10-1F aren't possible... those would be slower in theory)
576
577 SUSTAIN
578 -------
579 - no terminating condition except for voice off
580 - Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
581 - Sd=1 (decrease) behavior:
582 Linear sustain decrease:
583 - line extends to 0x00000000
584 - decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
585 Logarithmic sustain decrease:
586 - current line ends at (envelope_level & 0x07FFFFFF)
587 - decrement per sample depends on (envelope_level>>28)&0x7
588 0: ratelogtable[(Sr^0x7F)-0x1B+0]
589 1: ratelogtable[(Sr^0x7F)-0x1B+4]
590 2: ratelogtable[(Sr^0x7F)-0x1B+6]
591 3: ratelogtable[(Sr^0x7F)-0x1B+8]
592 4: ratelogtable[(Sr^0x7F)-0x1B+9]
593 5: ratelogtable[(Sr^0x7F)-0x1B+10]
594 6: ratelogtable[(Sr^0x7F)-0x1B+11]
595 7: ratelogtable[(Sr^0x7F)-0x1B+12]
596
597 RELEASE
598 -------
599 - if the envelope level has overflowed to negative, clip to 0 and QUIT.
600
601 Linear release mode:
602 - line extends to 0x00000000
603 - decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
604
605 Logarithmic release mode:
606 - line extends to (envelope_level & 0x0FFFFFFF)
607 - decrement per sample depends on (envelope_level>>28)&0x7
608 0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
609 1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
610 2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
611 3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
612 4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
613 5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
614 6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
615 7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
616
617 -----------------------------------------------------------------------------
618 */