DSP envelopes: Difference between revisions

From SNESdev Wiki
Jump to navigationJump to search
(→‎Gain Timings: finish the left hand columns)
(→‎ADSR Envelope: Add ADSR envelope diagram)
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Timings of the [[S-SMP]] DSP envelope and gain.
The envelope value of each [[S-DSP]] voice is driven by either an ADSR envelope, or a gain control. This gives an additional way to automatically shape the volume of the voice over time, aside from its '''VOL''' registers.


== ADSR Envelope Timings ==
Internally the envelope is an 11-bit value multiplied by by the voice output. The '''ENVX''' value that can be read from the DSP contains only the high 7 bits.
 
See:
* [[S-SMP#ADSR|ADSR]]
* [[S-SMP#GAIN|GAIN]]
 
== ADSR Envelope ==
 
The ADSR describes a 4 stage envelope:
* '''Attack''' begins at key-on, rising from 0 to full over a chosen amount of time.
* '''Decay''' lowers from full to a chosen Sustain Level.
* '''Sustain''' exponential decay from Sustain Level to 0 (if the Sustain Rate is non-zero).
* '''Release''' begins at key-off, lowering to 0 with an fixed decay.
 
[[File:Adsr_envelope.svg]]
 
 
See: [[S-SMP#ADSR|S-SMP ADSR]]
 
{| class="wikitable"
! Name
! Address
! Bits
! Notes
|-
! ADSR (1)
! $X5
| style="text-align: right" | <tt style="white-space: nowrap">EDDD AAAA</tt>
| ADSR enable (E), decay rate (D), attack rate (A).
|-
! ADSR (2)
! $X6
| style="text-align: right" | <tt style="white-space: nowrap">LLLR RRRR</tt>
| Sustain level (SL), sustain rate (SR).
|}
 
 
At a rate according to the [[#Period Table|period table]] the following action is performed, and the envelope is clamped to 0-2047 ($7FF):
* Attack at period[A*2+1]: adds 32, or if A=$F adds 1024 ($400).
* Decay at period[D*2+16]: <tt>envelope -= 1</tt>, then <tt>envelope -= envelope >> 8</tt>.
* Sustain at period[SR]: <tt>envelope -= 1</tt>, then <tt>envelope -= envelope >> 8</tt>.
* Release: <tt>envelope -= 8</tt> every sample.
 
This table of timings gives the resulting time taken by the above operations:
* Attack is the time from 0 to full.
* Decay is the time from full to sustain level.
* Sustain is the time from full to 0.


{|
{|
Line 71: Line 117:


{| class="wikitable"
{| class="wikitable"
! colspan=4 | ADSR Release
! colspan=4 | ADSR Sustain
|-
|-
! R !! Time (ms) !! R !! Time (ms)
! R !! Time (ms) !! R !! Time (ms)
Line 112: Line 158:
== Gain Timings ==
== Gain Timings ==


The odd linear gain rates are equivalent to the attack envelope rates (except for the fastest entry). The exponential decrease gain is equivalent to the release envelope.
See: [[S-SMP#GAIN|S-SMP GAIN]]
 
{| class="wikitable"
! Name
! Address
! Bits
! Notes
|-
! GAIN
! $X7
| style="text-align: right" | <tt style="white-space: nowrap">0VVV VVVV</tt><br/> <tt style="white-space: nowrap">1MMV VVVV</tt>
| Mode (M), value (V).
|}


'''TODO: ONLY THE FIRST 3 ROWS OF THIS TABLE ARE CORRECT SO FAR'''
At a rate according to the [[#Period Table|period table]] the following action is performed, and the envelope is clamped to 0-2047 ($7FF):
* Linear gain adds or subtracts 32.
* Bent gain adds 32 if below 1536 ($600), or 8 if above.
* Exponential is two steps: <tt>envelope -= 1</tt>, then: <tt>envelope -= envelope >> 8</tt>.
 
This table gives times taken between 0 volume and full volume (or the reverse):


{| class="wikitable"
{| class="wikitable"
Line 152: Line 215:
|-
|-
! $83
! $83
| 3100
| 2600
! $A3
! $A3
| 28000
| 24000
! $C3
! $C3
| 3100
| 2600
! $E3
! $E3
| 5400
| 4600
|-
|-
! $84
! $84
| 3100
| 2000
! $A4
! $A4
| 28000
| 19000
! $C4
! $C4
| 3100
| 2000
! $E4
! $E4
| 5400
| 3500
|-
|-
! $85
! $85
| 3100
| 1500
! $A5
! $A5
| 28000
| 14000
! $C5
! $C5
| 3100
| 1500
! $E5
! $E5
| 5400
| 2600
|-
|-
! $86
! $86
| 3100
| 1300
! $A6
! $A6
| 28000
| 12000
! $C6
! $C6
| 3100
| 1300
! $E6
! $E6
| 5400
| 2300
|-
|-
! $87
! $87
| 3100
| 1000
! $A7
! $A7
| 28000
| 9400
! $C7
! $C7
| 3100
| 1000
! $E7
! $E7
| 5400
| 1800
|-
|-
! $88
! $88
| 3100
| 770
! $A8
! $A8
| 28000
| 7100
! $C8
! $C8
| 3100
| 770
! $E8
! $E8
| 5400
| 1300
|-
|-
! $89
! $89
| 3100
| 640
! $A9
! $A9
| 28000
| 5900
! $C9
! $C9
| 3100
| 640
! $E9
! $E9
| 5400
| 1100
|-
|-
! $8A
! $8A
| 3100
| 510
! $AA
! $AA
| 28000
| 4700
! $CA
! $CA
| 3100
| 510
! $EA
! $EA
| 5400
| 900
|-
|-
! $8B
! $8B
| 3100
| 380
! $AB
! $AB
| 28000
| 3500
! $CB
! $CB
| 3100
| 380
! $EB
! $EB
| 5400
| 670
|-
|-
! $8C
! $8C
| 3100
| 320
! $AC
! $AC
| 28000
| 2900
! $CC
! $CC
| 3100
| 320
! $EC
! $EC
| 5400
| 560
|-
|-
! $8D
! $8D
| 3100
| 260
! $AD
! $AD
| 28000
| 2400
! $CD
! $CD
| 3100
| 260
! $ED
! $ED
| 5400
| 450
|-
|-
! $8E
! $8E
| 3100
| 190
! $AE
! $AE
| 28000
| 1800
! $CE
! $CE
| 3100
| 190
! $EE
! $EE
| 5400
| 340
|-
|-
! $8F
! $8F
| 3100
| 160
! $AF
! $AF
| 28000
| 1500
! $CF
! $CF
| 3100
| 160
! $EF
! $EF
| 5400
| 280
|-
|-
! $90
! $90
| 3100
| 130
! $B0
! $B0
| 28000
| 1200
! $D0
! $D0
| 3100
| 130
! $F0
! $F0
| 5400
| 220
|-
|-
! $91
! $91
| 3100
| 96
! $B1
! $B1
| 28000
| 880
! $D1
! $D1
| 3100
| 96
! $F1
! $F1
| 5400
| 170
|-
|-
! $92
! $92
| 3100
| 80
! $B2
! $B2
| 28000
| 740
! $D2
! $D2
| 3100
| 80
! $F2
! $F2
| 5400
| 140
|-
|-
! $93
! $93
| 3100
| 64
! $B3
! $B3
| 28000
| 590
! $D3
! $D3
| 3100
| 64
! $F3
! $F3
| 5400
| 110
|-
|-
! $94
! $94
| 3100
| 48
! $B4
! $B4
| 28000
| 440
! $D4
! $D4
| 3100
| 48
! $F4
! $F4
| 5400
| 84
|-
|-
! $95
! $95
| 3100
| 40
! $B5
! $B5
| 28000
| 370
! $D5
! $D5
| 3100
| 40
! $F5
! $F5
| 5400
| 70
|-
|-
! $96
! $96
| 3100
| 32
! $B6
! $B6
| 28000
| 290
! $D6
! $D6
| 3100
| 32
! $F6
! $F6
| 5400
| 56
|-
|-
! $97
! $97
| 3100
| 24
! $B7
! $B7
| 28000
| 220
! $D7
! $D7
| 3100
| 24
! $F7
! $F7
| 5400
| 42
|-
|-
! $98
! $98
| 3100
| 20
! $B8
! $B8
| 28000
| 180
! $D8
! $D8
| 3100
| 20
! $F8
! $F8
| 5400
| 35
|-
|-
! $99
! $99
| 3100
| 16
! $B9
! $B9
| 28000
| 150
! $D9
! $D9
| 3100
| 16
! $F9
! $F9
| 5400
| 28
|-
|-
! $9A
! $9A
| 3100
| 12
! $BA
! $BA
| 28000
| 110
! $DA
! $DA
| 3100
| 12
! $FA
! $FA
| 5400
| 21
|-
|-
! $9B
! $9B
| 3100
| 10
! $BB
! $BB
| 28000
| 92
! $DB
! $DB
| 3100
| 10
! $FB
! $FB
| 5400
| 18
|-
|-
! $9C
! $9C
| 3100
| 8
! $BC
! $BC
| 28000
| 74
! $DC
! $DC
| 3100
| 8
! $FC
! $FC
| 5400
| 14
|-
|-
! $9D
! $9D
| 3100
| 6
! $DD
! $DD
| 28000
| 55
! $BD
! $BD
| 3100
| 6
! $FD
! $FD
| 5400
| 11
|-
|-
! $9E
! $9E
| 3100
| 4
! $BE
! $BE
| 28000
| 37
! $DE
! $DE
| 3100
| 4
! $FE
! $FE
| 5400
| 7
|-
|-
! $9F
! $9F
| 3100
| 2
! $BF
! $BF
| 28000
| 18
! $DF
! $DF
| 3100
| 2
! $FF
! $FF
| 5400
| 3.5
|}
 
== Period Table ==
 
The rate of DSP envelope events are controlled by a common table of 32 periods. Each entry is how many S-SMP clocks elapse per envelope operation. The table is arranged in groups of 3.
 
Additionally, each column of periods appears to have a delay offset applied to it, affecting when the operation occurs. If <tt>counter</tt> is counting down the number of S-SMP clocks elapsed since reset, the envelope operation is applied when the following is true:
* <tt>0 == (counter + offset[rate]) % period[rate]</tt>
 
The counter begins at 0 after reset, and decrements on each S-SMP clock, wrapping to $77FF (30,720) when it would go below 0<ref>[https://www.romhacking.net/documents/191/ apudsp_jwdonal.txt] - Anomie's S-DSP document.</ref>. (The first clock after reset will wrap.)
 
{|
| style="vertical-align: top" |
 
{| class="wikitable"
! colspan=16 | DSP Period Table
|-
! / !! +0 !! +1 !! +2
|-
! 0
| Infinite || 2048 || 1536
|-
! 3
| 1280 || 1024 || 768
|-
! 6
| 640  || 512  || 384
|-
! 9
| 320  || 256  || 192
|-
! 12
| 160  || 128  || 96
|-
! 15
| 80  || 64  || 48
|-
! 18
| 40  || 32  || 24
|-
! 21
| 20  || 16  || 12
|-
! 24
| 10  || 8    || 6
|-
! 27
| 5    || 4    || 3
|-
! 30
| 2    || 1    || -
|}
 
| style="vertical-align: top" |
 
{| class="wikitable"
! colspan=16 | DSP Period Offset
|-
! / !! +0 !! +1 !! +2
|-
! 0
| Never || 0 || 1040
|-
! 3
| 536 || 0 || 1040
|-
! 6
| 536 || 0 || 1040
|-
! 9
| 536 || 0 || 1040
|-
! 12
| 536 || 0 || 1040
|-
! 15
| 536 || 0 || 1040
|-
! 18
| 536 || 0 || 1040
|-
! 21
| 536 || 0 || 1040
|-
! 24
| 536 || 0 || 1040
|-
! 27
| 536 || 0 || 1040
|-
! 30
| 536 || 0 || -
|}
 
|}
|}
Note that most of the offsets given above are effectively much smaller, given that they are modulo (%) with their associated period, but the modulo-equivalent larger values shown here demonstrate the symmetry between columns.
== References ==
<References/>


[[Category:Sound]]
[[Category:Sound]]

Latest revision as of 12:21, 10 May 2024

The envelope value of each S-DSP voice is driven by either an ADSR envelope, or a gain control. This gives an additional way to automatically shape the volume of the voice over time, aside from its VOL registers.

Internally the envelope is an 11-bit value multiplied by by the voice output. The ENVX value that can be read from the DSP contains only the high 7 bits.

See:

ADSR Envelope

The ADSR describes a 4 stage envelope:

  • Attack begins at key-on, rising from 0 to full over a chosen amount of time.
  • Decay lowers from full to a chosen Sustain Level.
  • Sustain exponential decay from Sustain Level to 0 (if the Sustain Rate is non-zero).
  • Release begins at key-off, lowering to 0 with an fixed decay.

Adsr envelope.svg


See: S-SMP ADSR

Name Address Bits Notes
ADSR (1) $X5 EDDD AAAA ADSR enable (E), decay rate (D), attack rate (A).
ADSR (2) $X6 LLLR RRRR Sustain level (SL), sustain rate (SR).


At a rate according to the period table the following action is performed, and the envelope is clamped to 0-2047 ($7FF):

  • Attack at period[A*2+1]: adds 32, or if A=$F adds 1024 ($400).
  • Decay at period[D*2+16]: envelope -= 1, then envelope -= envelope >> 8.
  • Sustain at period[SR]: envelope -= 1, then envelope -= envelope >> 8.
  • Release: envelope -= 8 every sample.

This table of timings gives the resulting time taken by the above operations:

  • Attack is the time from 0 to full.
  • Decay is the time from full to sustain level.
  • Sustain is the time from full to 0.
ADSR Attack
A Time (ms)
$0 4100
$1 2600
$2 1500
$3 1000
$4 640
$5 380
$6 260
$7 160
$8 96
$9 64
$A 40
$B 24
$C 16
$D 10
$E 6
$F 0
ADSR Decay
D Time (ms)
0 1200
1 740
2 440
3 290
4 180
5 110
6 74
7 37
ADSR Sustain
R Time (ms) R Time (ms)
$00 Infinite $10 1200
$01 38000 $11 880
$02 28000 $12 740
$03 24000 $13 590
$04 19000 $14 440
$05 14000 $15 370
$06 12000 $16 290
$07 9400 $17 220
$08 7100 $18 180
$09 5900 $19 150
$0A 4700 $1A 110
$0B 3500 $1B 92
$0C 2900 $1C 74
$0D 2400 $1D 55
$0E 1800 $1E 37
$0F 1500 $1F 18

Gain Timings

See: S-SMP GAIN

Name Address Bits Notes
GAIN $X7 0VVV VVVV
1MMV VVVV
Mode (M), value (V).

At a rate according to the period table the following action is performed, and the envelope is clamped to 0-2047 ($7FF):

  • Linear gain adds or subtracts 32.
  • Bent gain adds 32 if below 1536 ($600), or 8 if above.
  • Exponential is two steps: envelope -= 1, then: envelope -= envelope >> 8.

This table gives times taken between 0 volume and full volume (or the reverse):

GAIN
Decrease Linear Decrease Exponential Increase Linear Increase Bent
V Time (ms) V Time (ms) V Time (ms) V Time (ms)
$80 Infinite $A0 Infinite $C0 Infinite $E0 Infinite
$81 4100 $A1 38000 $C1 4100 $E1 7200
$82 3100 $A2 28000 $C2 3100 $E2 5400
$83 2600 $A3 24000 $C3 2600 $E3 4600
$84 2000 $A4 19000 $C4 2000 $E4 3500
$85 1500 $A5 14000 $C5 1500 $E5 2600
$86 1300 $A6 12000 $C6 1300 $E6 2300
$87 1000 $A7 9400 $C7 1000 $E7 1800
$88 770 $A8 7100 $C8 770 $E8 1300
$89 640 $A9 5900 $C9 640 $E9 1100
$8A 510 $AA 4700 $CA 510 $EA 900
$8B 380 $AB 3500 $CB 380 $EB 670
$8C 320 $AC 2900 $CC 320 $EC 560
$8D 260 $AD 2400 $CD 260 $ED 450
$8E 190 $AE 1800 $CE 190 $EE 340
$8F 160 $AF 1500 $CF 160 $EF 280
$90 130 $B0 1200 $D0 130 $F0 220
$91 96 $B1 880 $D1 96 $F1 170
$92 80 $B2 740 $D2 80 $F2 140
$93 64 $B3 590 $D3 64 $F3 110
$94 48 $B4 440 $D4 48 $F4 84
$95 40 $B5 370 $D5 40 $F5 70
$96 32 $B6 290 $D6 32 $F6 56
$97 24 $B7 220 $D7 24 $F7 42
$98 20 $B8 180 $D8 20 $F8 35
$99 16 $B9 150 $D9 16 $F9 28
$9A 12 $BA 110 $DA 12 $FA 21
$9B 10 $BB 92 $DB 10 $FB 18
$9C 8 $BC 74 $DC 8 $FC 14
$9D 6 $DD 55 $BD 6 $FD 11
$9E 4 $BE 37 $DE 4 $FE 7
$9F 2 $BF 18 $DF 2 $FF 3.5

Period Table

The rate of DSP envelope events are controlled by a common table of 32 periods. Each entry is how many S-SMP clocks elapse per envelope operation. The table is arranged in groups of 3.

Additionally, each column of periods appears to have a delay offset applied to it, affecting when the operation occurs. If counter is counting down the number of S-SMP clocks elapsed since reset, the envelope operation is applied when the following is true:

  • 0 == (counter + offset[rate]) % period[rate]

The counter begins at 0 after reset, and decrements on each S-SMP clock, wrapping to $77FF (30,720) when it would go below 0[1]. (The first clock after reset will wrap.)

DSP Period Table
/ +0 +1 +2
0 Infinite 2048 1536
3 1280 1024 768
6 640 512 384
9 320 256 192
12 160 128 96
15 80 64 48
18 40 32 24
21 20 16 12
24 10 8 6
27 5 4 3
30 2 1 -
DSP Period Offset
/ +0 +1 +2
0 Never 0 1040
3 536 0 1040
6 536 0 1040
9 536 0 1040
12 536 0 1040
15 536 0 1040
18 536 0 1040
21 536 0 1040
24 536 0 1040
27 536 0 1040
30 536 0 -

Note that most of the offsets given above are effectively much smaller, given that they are modulo (%) with their associated period, but the modulo-equivalent larger values shown here demonstrate the symmetry between columns.

References

  1. apudsp_jwdonal.txt - Anomie's S-DSP document.