1
/***************************************************************************
4
begin : Wed May 15 2002
5
copyright : (C) 2002 by Pete Bernert
6
email : BlackDove@addcom.de
7
***************************************************************************/
9
/***************************************************************************
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. *
17
***************************************************************************/
19
//*************************************************************************//
20
// History of changes:
22
// 2003/05/14 - xodnizel
23
// - removed stopping of reverb on sample end
26
// - added Neill's ADSR timings
29
// - generic cleanup for the Peops release
31
//*************************************************************************//
37
// will be included from spu.c
40
////////////////////////////////////////////////////////////////////////
42
////////////////////////////////////////////////////////////////////////
44
unsigned long RateTable[160];
46
void InitADSR(void) // INIT ADSR
48
unsigned long r,rs,rd;int i;
50
memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file)
54
for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0
59
rd++;if(rd==5) {rd=1;rs*=2;}
61
if(r>0x3FFFFFFF) r=0x3FFFFFFF;
67
////////////////////////////////////////////////////////////////////////
69
void StartADSR(int ch) // MIX ADSR
71
s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
72
s_chan[ch].ADSRX.State=0;
73
s_chan[ch].ADSRX.EnvelopeVol=0;
76
////////////////////////////////////////////////////////////////////////
78
int MixADSR(int ch) // MIX ADSR
80
if(s_chan[ch].bStop) // should be stopped:
82
if(s_chan[ch].ADSRX.ReleaseModeExp)
84
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
86
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
87
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
88
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
89
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
90
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
91
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
92
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
93
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
98
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
101
if(s_chan[ch].ADSRX.EnvelopeVol<0)
103
s_chan[ch].ADSRX.EnvelopeVol=0;
105
//s_chan[ch].bReverb=0;
106
//s_chan[ch].bNoise=0;
109
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
110
return s_chan[ch].ADSRX.lVolume;
112
else // not stopped yet?
114
if(s_chan[ch].ADSRX.State==0) // -> attack
116
if(s_chan[ch].ADSRX.AttackModeExp)
118
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
119
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
121
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
125
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
128
if(s_chan[ch].ADSRX.EnvelopeVol<0)
130
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
131
s_chan[ch].ADSRX.State=1;
134
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
135
return s_chan[ch].ADSRX.lVolume;
137
//--------------------------------------------------//
138
if(s_chan[ch].ADSRX.State==1) // -> decay
140
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
142
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
143
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
144
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
145
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
146
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
147
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
148
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
149
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
152
if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
153
if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
155
s_chan[ch].ADSRX.State=2;
158
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
159
return s_chan[ch].ADSRX.lVolume;
161
//--------------------------------------------------//
162
if(s_chan[ch].ADSRX.State==2) // -> sustain
164
if(s_chan[ch].ADSRX.SustainIncrease)
166
if(s_chan[ch].ADSRX.SustainModeExp)
168
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
169
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
171
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
175
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
178
if(s_chan[ch].ADSRX.EnvelopeVol<0)
180
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
185
if(s_chan[ch].ADSRX.SustainModeExp)
187
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
189
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
190
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
191
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
192
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
193
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
194
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
195
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
196
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
201
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
204
if(s_chan[ch].ADSRX.EnvelopeVol<0)
206
s_chan[ch].ADSRX.EnvelopeVol=0;
209
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
210
return s_chan[ch].ADSRX.lVolume;
219
James Higgs ADSR investigations:
221
PSX SPU Envelope Timings
222
~~~~~~~~~~~~~~~~~~~~~~~~
224
First, here is an extract from doomed's SPU doc, which explains the basics
225
of the SPU "volume envelope":
227
*** doomed doc extract start ***
229
--------------------------------------------------------------------------
231
--------------------------------------------------------------------------
232
The SPU has 24 hardware voices. These voices can be used to reproduce sample
233
data, noise or can be used as frequency modulator on the next voice.
234
Each voice has it's own programmable ADSR envelope filter. The main volume
235
can be programmed independently for left and right output.
237
The ADSR envelope filter works as follows:
238
Ar = Attack rate, which specifies the speed at which the volume increases
239
from zero to it's maximum value, as soon as the note on is given. The
240
slope can be set to lineair or exponential.
241
Dr = Decay rate specifies the speed at which the volume decreases to the
242
sustain level. Decay is always decreasing exponentially.
243
Sl = Sustain level, base level from which sustain starts.
244
Sr = Sustain rate is the rate at which the volume of the sustained note
245
increases or decreases. This can be either lineair or exponential.
246
Rr = Release rate is the rate at which the volume of the note decreases
247
as soon as the note off is given.
255
|/___________________\________
258
The overal volume can also be set to sweep up or down lineairly or
259
exponentially from it's current value. This can be done seperately
262
Relevant SPU registers:
263
-------------------------------------------------------------
264
$1f801xx8 Attack/Decay/Sustain level
265
bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
266
desc.|Am| Ar |Dr |Sl |
268
Am 0 Attack mode Linear
274
-------------------------------------------------------------
275
$1f801xxa Sustain rate, Release Rate.
276
bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
277
desc.|Sm|Sd| 0| Sr |Rm|Rr |
279
Sm 0 sustain rate mode linear
281
Sd 0 sustain rate mode increase
285
1 Exponential decrease
288
Note: decay mode is always Expontial decrease, and thus cannot
290
-------------------------------------------------------------
291
$1f801xxc Current ADSR volume
292
bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
295
ADSRvol Returns the current envelope volume when
297
-- James' Note: return range: 0 -> 32767
299
*** doomed doc extract end ***
301
By using a small PSX proggie to visualise the envelope as it was played,
302
the following results for envelope timing were obtained:
304
1. Attack rate value (linear mode)
306
Attack value range: 0 -> 127
308
Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 |
309
-----------------------------------------------------------------
310
Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890|
312
Note: frames is no. of PAL frames to reach full volume (100%
315
Hmm, noticing that the time taken to reach full volume doubles
316
every time we add 4 to our attack value, we know the equation is
318
frames = k * 2 ^ (value / 4)
320
(You may ponder about envelope generator hardware at this point,
323
By substituting some stuff and running some checks, we get:
325
k = 0.00257 (close enuf)
328
frames = 0.00257 * 2 ^ (value / 4)
329
If you just happen to be writing an emulator, then you can probably
330
use an equation like:
332
%volume_increase_per_tick = 1 / frames
335
------------------------------------
337
ms=((1<<(value>>2))*514)/10000
338
------------------------------------
340
2. Decay rate value (only has log mode)
342
Decay value range: 0 -> 15
344
Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
345
------------------------------------------------
346
frames | | | | | 6 | 12 | 24 | 47 |
348
Note: frames here is no. of PAL frames to decay to 50% volume.
350
formula: frames = k * 2 ^ (value)
352
Substituting, we get: k = 0.00146
354
Further info on logarithmic nature:
355
frames to decay to sustain level 3 = 3 * frames to decay to
358
Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
361
Frag it - just use linear approx.
363
------------------------------------
365
ms=((1<<value)*292)/10000
366
------------------------------------
369
3. Sustain rate value (linear mode)
371
Sustain rate range: 0 -> 127
373
Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
374
-------------------------------------------
375
frames | 9 | 19 | 37 | 74 | 147| 293| 587|
377
Here, frames = no. of PAL frames for volume amplitude to go from 100%
378
to 0% (or vice-versa).
380
Same formula as for attack value, just a different value for k:
384
ie: frames = 0.00225 * 2 ^ (value / 4)
386
For emulation purposes:
388
%volume_increase_or_decrease_per_tick = 1 / frames
390
------------------------------------
392
ms=((1<<(value>>2))*450)/10000
393
------------------------------------
396
4. Release rate (linear mode)
398
Release rate range: 0 -> 31
400
Value | 13 | 14 | 15 | 16 | 17 |
401
---------------------------------------------------------------
402
frames | 18 | 36 | 73 | 146| 292|
404
Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
405
after "note-off" is triggered.
407
Formula: frames = k * 2 ^ (value)
411
------------------------------------
413
ms=((1<<value)*446)/10000
414
------------------------------------
419
Log stuff not figured out. You may get some clues from the "Decay rate"
420
stuff above. For emu purposes it may not be important - use linear
423
To get timings in millisecs, multiply frames by 20.
427
- James Higgs 17/6/2000
430
//---------------------------------------------------------------
432
OLD adsr mixing according to james' rules... has to be called
433
every one millisecond
436
long v,v2,lT,l1,l2,l3;
438
if(s_chan[ch].bStop) // psx wants to stop? -> release phase
440
if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now)
442
if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff
444
s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
445
s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
446
s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level
447
(s_chan[ch].ADSR.ReleaseTime*
448
s_chan[ch].ADSR.ReleaseVol)/1024;
450
// -> NO release exp mode used (yet)
451
v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume
452
lT=s_chan[ch].ADSR.lTime- // -> how much time is past?
453
s_chan[ch].ADSR.ReleaseStartTime;
454
l1=s_chan[ch].ADSR.ReleaseTime;
456
if(lT<l1) // -> we still have to release
458
v=v-((v*lT)/l1); // --> calc new volume
460
else // -> release is over: now really stop that sample
461
{v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
463
else // -> release IS 0: release at once
465
v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
469
{//--------------------------------------------------// not in release phase:
471
lT=s_chan[ch].ADSR.lTime;
472
l1=s_chan[ch].ADSR.AttackTime;
475
{ // no exp mode used (yet)
476
// if(s_chan[ch].ADSR.AttackModeExp)
487
{ // should be exp, but who cares? ;)
488
l2=s_chan[ch].ADSR.DecayTime;
489
v2=s_chan[ch].ADSR.SustainLevel;
497
{ // no exp mode used (yet)
498
l3=s_chan[ch].ADSR.SustainTime;
500
if(s_chan[ch].ADSR.SustainModeDec>0)
502
if(l3!=0) v2+=((v-v2)*lT)/l3;
507
if(l3!=0) v2-=(v2*lT)/l3;
512
if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
519
//----------------------------------------------------//
520
// ok, done for this channel, so increase time
522
s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms;
524
if(v>1024) v=1024; // adjust volume
526
s_chan[ch].ADSR.lVolume=v; // store act volume
528
return v; // return the volume factor
532
//-----------------------------------------------------------------------------
533
//-----------------------------------------------------------------------------
534
//-----------------------------------------------------------------------------
538
-----------------------------------------------------------------------------
540
Playstation SPU envelope timing notes
541
-----------------------------------------------------------------------------
543
This is preliminary. This may be wrong. But the model described herein fits
544
all of my experimental data, and it's just simple enough to sound right.
546
ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
547
The value returned by channel reg 0xC is (envelope_level>>16).
549
Each sample, an increment or decrement value will be added to or
550
subtracted from this envelope level.
552
Create the rate log table. The values double every 4 entries.
565
increments and decrements are in terms of ratelogtable[n]
566
n may exceed the table bounds (plan on n being between -32 and 127).
567
table values are all clipped between 0x00000000 and 0x3FFFFFFF
569
when you "voice on", the envelope is always fully reset.
570
(yes, it may click. the real thing does this too.)
572
envelope level begins at zero.
574
each state happens for at least 1 cycle
575
(transitions are not instantaneous)
576
this may result in some oddness: if the decay rate is uberfast, it will cut
577
the envelope from full down to half in one sample, potentially skipping over
582
- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
586
- line extends upward to 0x7FFFFFFF
587
- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
589
Logarithmic attack mode:
590
if envelope_level < 0x60000000:
591
- line extends upward to 0x60000000
592
- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
594
- line extends upward to 0x7FFFFFFF
595
- increment per sample is ratelogtable[(Ar^0x7F)-0x18]
599
- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
600
Do not clip to the sustain level.
601
- current line ends at (envelope_level & 0x07FFFFFF)
602
- decrement per sample depends on (envelope_level>>28)&0x7
603
0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
604
1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
605
2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
606
3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
607
4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
608
5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
609
6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
610
7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
611
(note that this is the same as the release rate formula, except that
612
decay rates 10-1F aren't possible... those would be slower in theory)
616
- no terminating condition except for voice off
617
- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
618
- Sd=1 (decrease) behavior:
619
Linear sustain decrease:
620
- line extends to 0x00000000
621
- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
622
Logarithmic sustain decrease:
623
- current line ends at (envelope_level & 0x07FFFFFF)
624
- decrement per sample depends on (envelope_level>>28)&0x7
625
0: ratelogtable[(Sr^0x7F)-0x1B+0]
626
1: ratelogtable[(Sr^0x7F)-0x1B+4]
627
2: ratelogtable[(Sr^0x7F)-0x1B+6]
628
3: ratelogtable[(Sr^0x7F)-0x1B+8]
629
4: ratelogtable[(Sr^0x7F)-0x1B+9]
630
5: ratelogtable[(Sr^0x7F)-0x1B+10]
631
6: ratelogtable[(Sr^0x7F)-0x1B+11]
632
7: ratelogtable[(Sr^0x7F)-0x1B+12]
636
- if the envelope level has overflowed to negative, clip to 0 and QUIT.
639
- line extends to 0x00000000
640
- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
642
Logarithmic release mode:
643
- line extends to (envelope_level & 0x0FFFFFFF)
644
- decrement per sample depends on (envelope_level>>28)&0x7
645
0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
646
1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
647
2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
648
3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
649
4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
650
5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
651
6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
652
7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
654
-----------------------------------------------------------------------------