~ubuntu-branches/debian/jessie/audacious-plugins/jessie

« back to all changes in this revision

Viewing changes to src/psf/peops2/adsr.c

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2012-02-20 00:28:16 UTC
  • mfrom: (1.1.16)
  • Revision ID: package-import@ubuntu.com-20120220002816-mgn4vhn314z6mubs
Tags: 3.2.1-1
* Team upload.
* New upstream bugfix release.
* Remove correct_spelling_error.diff, applied upstream.
* Refresh ffaudio.diff.
* Reintroduce src/psf/*, it seems DFSG clean now.
* Fix and update debian/copyright.
* Update watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/05/14 - xodnizel
 
23
// - removed stopping of reverb on sample end
 
24
//
 
25
// 2003/01/06 - Pete
 
26
// - added Neill's ADSR timings
 
27
//
 
28
// 2002/05/15 - Pete
 
29
// - generic cleanup for the Peops release
 
30
//
 
31
//*************************************************************************//
 
32
 
 
33
#include "stdafx.h"
 
34
 
 
35
#define _IN_ADSR
 
36
 
 
37
// will be included from spu.c
 
38
#ifdef _IN_SPU
 
39
 
 
40
////////////////////////////////////////////////////////////////////////
 
41
// ADSR func
 
42
////////////////////////////////////////////////////////////////////////
 
43
 
 
44
unsigned long RateTable[160];
 
45
 
 
46
void InitADSR(void)                                    // INIT ADSR
 
47
{
 
48
 unsigned long r,rs,rd;int i;
 
49
 
 
50
 memset(RateTable,0,sizeof(unsigned long)*160);        // build the rate table according to Neill's rules (see at bottom of file)
 
51
 
 
52
 r=3;rs=1;rd=0;
 
53
 
 
54
 for(i=32;i<160;i++)                                   // we start at pos 32 with the real values... everything before is 0
 
55
  {
 
56
   if(r<0x3FFFFFFF)
 
57
    {
 
58
     r+=rs;
 
59
     rd++;if(rd==5) {rd=1;rs*=2;}
 
60
    }
 
61
   if(r>0x3FFFFFFF) r=0x3FFFFFFF;
 
62
 
 
63
   RateTable[i]=r;
 
64
  }
 
65
}
 
66
 
 
67
////////////////////////////////////////////////////////////////////////
 
68
 
 
69
void StartADSR(int ch)                          // MIX ADSR
 
70
{
 
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;
 
74
}
 
75
 
 
76
////////////////////////////////////////////////////////////////////////
 
77
 
 
78
int MixADSR(int ch)                             // MIX ADSR
 
79
{
 
80
 if(s_chan[ch].bStop)                                  // should be stopped:
 
81
  {                                                    // do release
 
82
   if(s_chan[ch].ADSRX.ReleaseModeExp)
 
83
    {
 
84
     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
 
85
      {
 
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;
 
94
      }
 
95
    }
 
96
   else
 
97
    {
 
98
     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
 
99
    }
 
100
 
 
101
   if(s_chan[ch].ADSRX.EnvelopeVol<0)
 
102
    {
 
103
     s_chan[ch].ADSRX.EnvelopeVol=0;
 
104
     s_chan[ch].bOn=0;
 
105
     //s_chan[ch].bReverb=0;
 
106
     //s_chan[ch].bNoise=0;
 
107
    }
 
108
 
 
109
   s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
 
110
   return s_chan[ch].ADSRX.lVolume;
 
111
  }
 
112
 else                                                  // not stopped yet?
 
113
  {
 
114
   if(s_chan[ch].ADSRX.State==0)                       // -> attack
 
115
    {
 
116
     if(s_chan[ch].ADSRX.AttackModeExp)
 
117
      {
 
118
       if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
 
119
        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
 
120
       else
 
121
        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
 
122
      }
 
123
     else
 
124
      {
 
125
       s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
 
126
      }
 
127
 
 
128
     if(s_chan[ch].ADSRX.EnvelopeVol<0)
 
129
      {
 
130
       s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
 
131
       s_chan[ch].ADSRX.State=1;
 
132
      }
 
133
 
 
134
     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
 
135
     return s_chan[ch].ADSRX.lVolume;
 
136
    }
 
137
   //--------------------------------------------------//
 
138
   if(s_chan[ch].ADSRX.State==1)                       // -> decay
 
139
    {
 
140
     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
 
141
      {
 
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;
 
150
      }
 
151
 
 
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)
 
154
      {
 
155
       s_chan[ch].ADSRX.State=2;
 
156
      }
 
157
 
 
158
     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
 
159
     return s_chan[ch].ADSRX.lVolume;
 
160
    }
 
161
   //--------------------------------------------------//
 
162
   if(s_chan[ch].ADSRX.State==2)                       // -> sustain
 
163
    {
 
164
     if(s_chan[ch].ADSRX.SustainIncrease)
 
165
      {
 
166
       if(s_chan[ch].ADSRX.SustainModeExp)
 
167
        {
 
168
         if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
 
169
          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
 
170
         else
 
171
          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
 
172
        }
 
173
       else
 
174
        {
 
175
         s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
 
176
        }
 
177
 
 
178
       if(s_chan[ch].ADSRX.EnvelopeVol<0)
 
179
        {
 
180
         s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
 
181
        }
 
182
      }
 
183
     else
 
184
      {
 
185
       if(s_chan[ch].ADSRX.SustainModeExp)
 
186
        {
 
187
         switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
 
188
          {
 
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;
 
197
          }
 
198
        }
 
199
       else
 
200
        {
 
201
         s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
 
202
        }
 
203
 
 
204
       if(s_chan[ch].ADSRX.EnvelopeVol<0)
 
205
        {
 
206
         s_chan[ch].ADSRX.EnvelopeVol=0;
 
207
        }
 
208
      }
 
209
     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
 
210
     return s_chan[ch].ADSRX.lVolume;
 
211
    }
 
212
  }
 
213
 return 0;
 
214
}
 
215
 
 
216
#endif
 
217
 
 
218
/*
 
219
James Higgs ADSR investigations:
 
220
 
 
221
PSX SPU Envelope Timings
 
222
~~~~~~~~~~~~~~~~~~~~~~~~
 
223
 
 
224
First, here is an extract from doomed's SPU doc, which explains the basics
 
225
of the SPU "volume envelope":
 
226
 
 
227
*** doomed doc extract start ***
 
228
 
 
229
--------------------------------------------------------------------------
 
230
Voices.
 
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.
 
236
 
 
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.
 
248
 
 
249
     lvl |
 
250
       ^ |     /\Dr     __
 
251
     Sl _| _  / _ \__---  \
 
252
         |   /       ---__ \ Rr
 
253
         |  /Ar       Sr  \ \
 
254
         | /                \\
 
255
         |/___________________\________
 
256
                                  ->time
 
257
 
 
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
 
260
for left and right.
 
261
 
 
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         |
 
267
 
 
268
Am       0        Attack mode Linear
 
269
         1                    Exponential
 
270
 
 
271
Ar       0-7f     attack rate
 
272
Dr       0-f      decay rate
 
273
Sl       0-f      sustain level
 
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            |
 
278
 
 
279
Sm       0        sustain rate mode linear
 
280
         1                          exponential
 
281
Sd       0        sustain rate mode increase
 
282
         1                          decrease
 
283
Sr       0-7f     Sustain Rate
 
284
Rm       0        Linear decrease
 
285
         1        Exponential decrease
 
286
Rr       0-1f     Release Rate
 
287
 
 
288
Note: decay mode is always Expontial decrease, and thus cannot
 
289
be set.
 
290
-------------------------------------------------------------
 
291
$1f801xxc         Current ADSR volume
 
292
bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
 
293
desc.|ADSRvol                                        |
 
294
 
 
295
ADSRvol           Returns the current envelope volume when
 
296
                  read.
 
297
-- James' Note: return range: 0 -> 32767
 
298
 
 
299
*** doomed doc extract end ***
 
300
 
 
301
By using a small PSX proggie to visualise the envelope as it was played,
 
302
the following results for envelope timing were obtained:
 
303
 
 
304
1. Attack rate value (linear mode)
 
305
 
 
306
   Attack value range: 0 -> 127
 
307
 
 
308
   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |    | 80 |
 
309
   -----------------------------------------------------------------
 
310
   Frames | 11 | 21 | 42 | 84 | 169| 338| 676|    |2890|
 
311
 
 
312
   Note: frames is no. of PAL frames to reach full volume (100%
 
313
   amplitude)
 
314
 
 
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
 
317
   of form:
 
318
             frames = k * 2 ^ (value / 4)
 
319
 
 
320
   (You may ponder about envelope generator hardware at this point,
 
321
   or maybe not... :)
 
322
 
 
323
   By substituting some stuff and running some checks, we get:
 
324
 
 
325
       k = 0.00257              (close enuf)
 
326
 
 
327
   therefore,
 
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:
 
331
 
 
332
       %volume_increase_per_tick = 1 / frames
 
333
 
 
334
 
 
335
   ------------------------------------
 
336
   Pete:
 
337
   ms=((1<<(value>>2))*514)/10000
 
338
   ------------------------------------
 
339
 
 
340
2. Decay rate value (only has log mode)
 
341
 
 
342
   Decay value range: 0 -> 15
 
343
 
 
344
   Value  |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
 
345
   ------------------------------------------------
 
346
   frames |    |    |    |    |  6 | 12 | 24 | 47 |
 
347
 
 
348
   Note: frames here is no. of PAL frames to decay to 50% volume.
 
349
 
 
350
   formula: frames = k * 2 ^ (value)
 
351
 
 
352
   Substituting, we get: k = 0.00146
 
353
 
 
354
   Further info on logarithmic nature:
 
355
   frames to decay to sustain level 3  =  3 * frames to decay to
 
356
   sustain level 9
 
357
 
 
358
   Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
 
359
   50% volume.
 
360
 
 
361
   Frag it - just use linear approx.
 
362
 
 
363
   ------------------------------------
 
364
   Pete:
 
365
   ms=((1<<value)*292)/10000
 
366
   ------------------------------------
 
367
 
 
368
 
 
369
3. Sustain rate value (linear mode)
 
370
 
 
371
   Sustain rate range: 0 -> 127
 
372
 
 
373
   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
 
374
   -------------------------------------------
 
375
   frames |  9 | 19 | 37 | 74 | 147| 293| 587|
 
376
 
 
377
   Here, frames = no. of PAL frames for volume amplitude to go from 100%
 
378
   to 0% (or vice-versa).
 
379
 
 
380
   Same formula as for attack value, just a different value for k:
 
381
 
 
382
   k = 0.00225
 
383
 
 
384
   ie: frames = 0.00225 * 2 ^ (value / 4)
 
385
 
 
386
   For emulation purposes:
 
387
 
 
388
   %volume_increase_or_decrease_per_tick = 1 / frames
 
389
 
 
390
   ------------------------------------
 
391
   Pete:
 
392
   ms=((1<<(value>>2))*450)/10000
 
393
   ------------------------------------
 
394
 
 
395
 
 
396
4. Release rate (linear mode)
 
397
 
 
398
   Release rate range: 0 -> 31
 
399
 
 
400
   Value  | 13 | 14 | 15 | 16 | 17 |
 
401
   ---------------------------------------------------------------
 
402
   frames | 18 | 36 | 73 | 146| 292|
 
403
 
 
404
   Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
 
405
   after "note-off" is triggered.
 
406
 
 
407
   Formula: frames = k * 2 ^ (value)
 
408
 
 
409
   And so: k = 0.00223
 
410
 
 
411
   ------------------------------------
 
412
   Pete:
 
413
   ms=((1<<value)*446)/10000
 
414
   ------------------------------------
 
415
 
 
416
 
 
417
Other notes:
 
418
 
 
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
 
421
approx.
 
422
 
 
423
To get timings in millisecs, multiply frames by 20.
 
424
 
 
425
 
 
426
 
 
427
- James Higgs 17/6/2000
 
428
james7780@yahoo.com
 
429
 
 
430
//---------------------------------------------------------------
 
431
 
 
432
OLD adsr mixing according to james' rules... has to be called
 
433
every one millisecond
 
434
 
 
435
 
 
436
 long v,v2,lT,l1,l2,l3;
 
437
 
 
438
 if(s_chan[ch].bStop)                                  // psx wants to stop? -> release phase
 
439
  {
 
440
   if(s_chan[ch].ADSR.ReleaseVal!=0)                   // -> release not 0: do release (if 0: stop right now)
 
441
    {
 
442
     if(!s_chan[ch].ADSR.ReleaseVol)                   // --> release just started? set up the release stuff
 
443
      {
 
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;
 
449
      }
 
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;
 
455
 
 
456
     if(lT<l1)                                         // -> we still have to release
 
457
      {
 
458
       v=v-((v*lT)/l1);                                // --> calc new volume
 
459
      }
 
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;}
 
462
    }
 
463
   else                                                // -> release IS 0: release at once
 
464
    {
 
465
     v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
 
466
    }
 
467
  }
 
468
 else
 
469
  {//--------------------------------------------------// not in release phase:
 
470
   v=1024;
 
471
   lT=s_chan[ch].ADSR.lTime;
 
472
   l1=s_chan[ch].ADSR.AttackTime;
 
473
 
 
474
   if(lT<l1)                                           // attack
 
475
    {                                                  // no exp mode used (yet)
 
476
//     if(s_chan[ch].ADSR.AttackModeExp)
 
477
//      {
 
478
//       v=(v*lT)/l1;
 
479
//      }
 
480
//     else
 
481
      {
 
482
       v=(v*lT)/l1;
 
483
      }
 
484
     if(v==0) v=1;
 
485
    }
 
486
   else                                                // decay
 
487
    {                                                  // should be exp, but who cares? ;)
 
488
     l2=s_chan[ch].ADSR.DecayTime;
 
489
     v2=s_chan[ch].ADSR.SustainLevel;
 
490
 
 
491
     lT-=l1;
 
492
     if(lT<l2)
 
493
      {
 
494
       v-=(((v-v2)*lT)/l2);
 
495
      }
 
496
     else                                              // sustain
 
497
      {                                                // no exp mode used (yet)
 
498
       l3=s_chan[ch].ADSR.SustainTime;
 
499
       lT-=l2;
 
500
       if(s_chan[ch].ADSR.SustainModeDec>0)
 
501
        {
 
502
         if(l3!=0) v2+=((v-v2)*lT)/l3;
 
503
         else      v2=v;
 
504
        }
 
505
       else
 
506
        {
 
507
         if(l3!=0) v2-=(v2*lT)/l3;
 
508
         else      v2=v;
 
509
        }
 
510
 
 
511
       if(v2>v)  v2=v;
 
512
       if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
 
513
 
 
514
       v=v2;
 
515
      }
 
516
    }
 
517
  }
 
518
 
 
519
 //----------------------------------------------------//
 
520
 // ok, done for this channel, so increase time
 
521
 
 
522
 s_chan[ch].ADSR.lTime+=1;                             // 1 = 1.020408f ms;
 
523
 
 
524
 if(v>1024)     v=1024;                                // adjust volume
 
525
 if(v<0)        v=0;
 
526
 s_chan[ch].ADSR.lVolume=v;                            // store act volume
 
527
 
 
528
 return v;                                             // return the volume factor
 
529
*/
 
530
 
 
531
 
 
532
//-----------------------------------------------------------------------------
 
533
//-----------------------------------------------------------------------------
 
534
//-----------------------------------------------------------------------------
 
535
 
 
536
 
 
537
/*
 
538
-----------------------------------------------------------------------------
 
539
Neill Corlett
 
540
Playstation SPU envelope timing notes
 
541
-----------------------------------------------------------------------------
 
542
 
 
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.
 
545
 
 
546
ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
 
547
The value returned by channel reg 0xC is (envelope_level>>16).
 
548
 
 
549
Each sample, an increment or decrement value will be added to or
 
550
subtracted from this envelope level.
 
551
 
 
552
Create the rate log table.  The values double every 4 entries.
 
553
   entry #0 = 4
 
554
 
 
555
    4, 5, 6, 7,
 
556
    8,10,12,14,
 
557
   16,20,24,28, ...
 
558
 
 
559
   entry #40 = 4096...
 
560
   entry #44 = 8192...
 
561
   entry #48 = 16384...
 
562
   entry #52 = 32768...
 
563
   entry #56 = 65536...
 
564
 
 
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
 
568
 
 
569
when you "voice on", the envelope is always fully reset.
 
570
(yes, it may click. the real thing does this too.)
 
571
 
 
572
envelope level begins at zero.
 
573
 
 
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
 
578
the sustain level
 
579
 
 
580
ATTACK
 
581
------
 
582
- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
 
583
  proceed to DECAY.
 
584
 
 
585
Linear attack mode:
 
586
- line extends upward to 0x7FFFFFFF
 
587
- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
 
588
 
 
589
Logarithmic attack mode:
 
590
if envelope_level < 0x60000000:
 
591
  - line extends upward to 0x60000000
 
592
  - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
 
593
else:
 
594
  - line extends upward to 0x7FFFFFFF
 
595
  - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
 
596
 
 
597
DECAY
 
598
-----
 
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)
 
613
 
 
614
SUSTAIN
 
615
-------
 
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]
 
633
 
 
634
RELEASE
 
635
-------
 
636
- if the envelope level has overflowed to negative, clip to 0 and QUIT.
 
637
 
 
638
Linear release mode:
 
639
- line extends to 0x00000000
 
640
- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
 
641
 
 
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]
 
653
 
 
654
-----------------------------------------------------------------------------
 
655
*/
 
656