              ;***************************************************************
              ; 
              ; A stereo reverb for the DSP56001 signal processor.
              ; Developed by Quinn Jensen (jensenq@qcj.icon.com) using
              ; Dr. Vercoe and company's csound code as a reference for the 
              ; configuration and gain values.
              ; 
              ;       NOTE - A much improved reverb algorithm is in sixcomb.a56
              ; 
              ; This program fragment implements a stereo reberb effect
              ; on a DSP56001 processor.  The "depth" and wet/dry mix are
              ; adjustable.  The following filter configuration is employed:
              ;
              ;
              ;  Left in ------+------- "dry" gain -----------> sum -----> Left out
              ;                |                                 ^
              ;                v                                 |
              ;               sum --> reverb --> "wet" gain -----+
              ;                ^                                 |
              ;                |                                 v -
              ;  Right in -----+------- "dry" gain -----------> sum -----> Right out
              ;
              ;
              ; Note that the reverb path output is negated before summing with the
              ; right input signal.  This throws in 180 degrees of phase shift
              ; making for interesting results even with mono inputs 
              ; (i.e. Left in == Right in).
              ; 
              ; The reverb element looks like this:
              ;
              ;
              ; Input ----+-----> comb1 ------+
              ;           |                   |
              ;           +-----> comb2 ---\  v
              ;           |                  sum -----> allpass1 --> allpass2 ---> output
              ;           +-----> comb3 ---/  ^
              ;           |                   |
              ;           +-----> comb4 ------+
              ;
              ; Each comb stage looks like this:
              ;
              ;                        +---- gain <-----+
              ;                        |                |
              ;                        v                |
              ; Input ---> gain ----> sum ---> delay ---+--> out
              ;
              ;
              ; The allpass stages look like:
              ;
              ;                         +--------- gain <---------+
              ;                         |                         |
              ;                         v                         |
              ; Input ---> gain --+--> sum ---> delay ---> sum ---+----> out
              ;                   |                         ^
              ;                   |                         |
              ;                   +--------> gain ----------+
              ;
              ; or,
              ;
              ;                             +-------> gain ----+
              ;                             |                  |
              ;                             |                  v
              ; Input ---> gain ----> sum --+--> delay --+--> sum -----> out
              ;                        ^                 |
              ;                        |                 |
              ;                        +----- gain <-----+
              ;
              ;
              ; I've seen both configurations in the literature, so I plotted the
              ; Z-transform and they are equivalent in the steady state.  They are indeed
              ; all-pass in the steady state but are supposed to have a subtle, discernable
              ; effect in "transient" audio signals.
              ;
              ; I think it could really use a couple more comb stages to fill in some of the 
              ; graininess.  The best possible "diffusion" is desired.  By the way, 
              ; I'd enjoy seeing any optimizations to the code.
              ;
              
              ;hardware specific initialization code
              
              include "tdsg.a56"
              
              ;***************************************************************
              ;
              ;       Data and constants
              ;
              ;***************************************************************
              
P:0076        dot                             ;remember where we were in P-space
X:0010                org     x:$10           ;put runtime variables in on-chip X-space
              
              ; A spreadsheet was used to calculate the following numbers
              ;
              ; The gain of each feedback stage is given by
              ;
              ;       feedback gain = exp(delay * ln(.001)/duration)
              ;
              ; where "delay" is the delay of the comb or allpass stage in seconds,
              ; and "duration" is the time in seconds for the reverberated sound
              ; to decay to 1/1000 of its original amplitude.
              ;
              
              ;  Reverb filter lengths and coefficients  
              ;  Sun Aug  4 16:36:16 1991    
              ;  
              ;      Sample rate               32.5520830 kHz      
              ;      Reverb duration            4.0000000 s        
              ;  
              ;  stage    delay(ms)    length        gain    actual
              ;  -----------------------------------------------------       
              ;  Comb1   29.7000000       967   0.9500031     29.71
              ;  Comb2   37.1000000      1208   0.9379399     37.11
              ;  Comb3   41.1000000      1338   0.9314831     41.10
              ;  Comb4   43.7000000      1423   0.9273101     43.71
              ;  All-1    5.0000000       163   0.9914025      5.01
              ;  All-2    1.7000000        55   0.9970685      1.69
              
  0.340909    in_atten equ                      0.3409091
 0.0416667    comb_atten equ                    0.0416667
       0.4    dry_init equ                      0.4000000     ; initial "dry" gain
      0.99    reverb_init equ                   0.9900000     ; initial "wet" gain
              
              ; comb 1 data and parameters
              
004000        c1d equ                   $4000
X:0010 004000 c1r  dc                     c1d
0003C6        c1m equ                     966
  0.950003    c1c equ                           0.9500031
              
              ; comb 2 data and parameters
              
004800        c2d equ          c1d+      2048
X:0011 004800 c2r  dc                     c2d
0004B7        c2m equ                    1207
   0.93794    c2c equ                           0.9379399
              
              ; comb 3 data and parameters
              
005000        c3d equ          c2d+      2048
X:0012 005000 c3r  dc                     c3d
000539        c3m equ                    1337
  0.931483    c3c equ                           0.9314831
              
              ; comb 4 data and parameters
              
005800        c4d equ          c3d+      2048
X:0013 005800 c4r  dc                     c4d
00058E        c4m equ                    1422
   0.92731    c4c equ                           0.9273101
              
              ; allpass 1 data and parameters
              
006000        a1d equ          c4d+      2048
X:0014 006000 a1r  dc                     a1d
0000A2        a1m equ                     162
  0.991403    a1c equ                           0.9914025
              
              ; allpass 2 data and parameters
              
006800        a2d equ          a1d+      2048
X:0015 006800 a2r  dc                     a2d
000036        a2m equ                      54
  0.997068    a2c equ                           0.9970685
              
Y:0000                org     y:$0
              
      0.99    reverb_on equ   reverb_init
000000        reverb_off equ  0
              
Y:0000        reverb_gain
Y:0000 7EB852         dc      reverb_on
Y:0001        dry_gain
Y:0001 333333         dc      dry_init
              
P:0076                org     p:dot           ;go back to P-space
              
              ;*****************************************************
              ;
              ; reverb initialization code
              ;
              ;*****************************************************
              
P:0076        hf_init
P:0076 00000C         rts
              
              ;*****************************************************
              ;
              ; run-time controls
              ;
              ;*****************************************************
              
P:0077        eff1_on         ;enable reverb
P:0077 46F400         move                    #reverb_on,y0
P:0078 7EB852
P:0079 4E0000         move                    y0,y:<reverb_gain
P:007A 00000C         rts
              
P:007B        eff1_off        ;bypass reverb
P:007B 46F400         move                    #reverb_off,y0
P:007C 000000
P:007D 4E0000         move                    y0,y:<reverb_gain
P:007E 00000C         rts
              
              ;*****************************************************
              ;
              ; interrupt time calculations
              ;
              ;*****************************************************
              
              ;
              ; fs = 32.552083 kHz
              ;
              
P:007F        hf_comp
P:007F 0D0066         jsr     <saveregs
              ;
              ;       L/R mix
              ;
P:0080 45F413         clr     a       #in_atten,x1            ;clr a, get scale for mix
P:0081 2BA2E9
P:0082 448000         move            x:<in_l,x0              ;get left in
P:0083 440200         move            x0,x:<in_ls             ;save
P:0084 4481A3         macr    x0,x1,a x:<in_r,x0              ;a = scale * left, get right
P:0085 4403A3         macr    x0,x1,a x0,x:<in_rs             ;a += scale * right, save right
P:0086 21C61B         clr     b               a,y0            ;y0 goes to the combs, b is sum
              ;
              ;       comb 1 
              ;
P:0087 609000         move            x:<c1r,r0
P:0088 05F420         movec           #c1m,m0
P:0089 0003C6
P:008A 20CE00         move                    y0,a
P:008B 45E000         move            x:(r0),x1
P:008C 44F468         add     x1,b    #c1c,x0
P:008D 7999B4
P:008E 2000A3         macr    x0,x1,a
P:008F 565800         move            a,x:(r0)+
P:0090 601000         move            r0,x:<c1r
              ;
              ;       comb 2
              ;
P:0091 609100         move            x:<c2r,r0
P:0092 05F420         movec           #c2m,m0
P:0093 0004B7
P:0094 20CE00         move                    y0,a
P:0095 45E000         move            x:(r0),x1
P:0096 44F468         add     x1,b    #c2c,x0
P:0097 780E6A
P:0098 2000A3         macr    x0,x1,a
P:0099 565800         move            a,x:(r0)+
P:009A 601100         move            r0,x:<c2r
              ;
              ;       comb 3
              ;
P:009B 609200         move            x:<c3r,r0
P:009C 05F420         movec           #c3m,m0
P:009D 000539
P:009E 20CE00         move                    y0,a
P:009F 45E000         move            x:(r0),x1
P:00A0 44F468         add     x1,b    #c3c,x0
P:00A1 773AD7
P:00A2 2000A3         macr    x0,x1,a
P:00A3 565800         move            a,x:(r0)+
P:00A4 601200         move            r0,x:<c3r
              ;
              ;       comb 4
              ;
P:00A5 609300         move            x:<c4r,r0
P:00A6 05F420         movec           #c4m,m0
P:00A7 00058E
P:00A8 20CE00         move                    y0,a
P:00A9 45E000         move            x:(r0),x1
P:00AA 44F468         add     x1,b    #c4c,x0
P:00AB 76B219
P:00AC 2000A3         macr    x0,x1,a
P:00AD 565800         move            a,x:(r0)+
P:00AE 601300         move            r0,x:<c4r
              ;
              ;       scale
              ;
P:00AF 12B400         move            #comb_atten,x0  b,y0
P:00B0 055556
P:00B1 2000D9         mpyr    x0,y0,b
              
              ;
              ;       allpass 1
              ;
P:00B2 609400         move            x:<a1r,r0
P:00B3 05F420         movec           #a1m,m0
P:00B4 0000A2
P:00B5 44F400         move            #a1c,x0
P:00B6 7EE647
P:00B7 45E000         move            x:(r0),x1
P:00B8 20AEAB         macr    x0,x1,b x1,a
P:00B9 21E600         move                    b,y0
P:00BA 5758D7         macr    -x0,y0,a b,x:(r0)+
P:00BB 601400         move            r0,x:<a1r
              ;
              ;       allpass 2
              ;
P:00BC 609500         move            x:<a2r,r0
P:00BD 05F420         movec           #a2m,m0
P:00BE 000036
P:00BF 44F400         move            #a2c,x0
P:00C0 7F9FF1
P:00C1 45E000         move            x:(r0),x1
P:00C2 20AFA3         macr    x0,x1,a x1,b
P:00C3 21C600         move                    a,y0
P:00C4 5658DF         macr    -x0,y0,b a,x:(r0)+
P:00C5 601500         move            r0,x:<a2r
              ;
              ;       output mix
              ;
P:00C6 21E400         move            b,x0
P:00C7 4E8000         move                    y:<reverb_gain,y0
P:00C8 4E81D9         mpyr    x0,y0,b         y:<dry_gain,y0
P:00C9 448200         move            x:<in_ls,x0
P:00CA 21EE00         move            b,a
P:00CB 4483D3         macr    x0,y0,a x:<in_rs,x0
P:00CC 5604DB         macr    x0,y0,b a,x:<out_l
P:00CD 570500         move            b,x:<out_r
              
P:00CE 0D006F         jsr     <restregs
P:00CF 00000C         rts
              
                      end
              

Summary of psect usage

                 section seg base last top      used       avail    total
-------------------------------------------------------------------------


Symbol Table
-------------------------------------
         ssi_int 000061
            ssix 000010
        eff1_off 00007B
         eff1_on 000077
        in_atten 0.3409091000
     init_stereo 000059
           start 000040
           in_rs 000003
           in_ls 000002
            in_r 000001
            in_l 000000
             dot 000076
      comb_atten 0.0416667000
        mainloop 000060
         hf_comp 00007F
         hf_init 000076
        saveregs 000066
           savey 00000B
           savex 00000A
          saveb2 000009
         saveb10 000008
          savea2 000007
         savea10 000006
        dry_gain 000001
        dry_init 0.4000000000
     reverb_gain 000000
      reverb_off 000000
       reverb_on 0.9900000000
     reverb_init 0.9900000000
        restregs 00006F
           out_r 000005
           out_l 000004
          m_scl1 00000F
          m_scl0 00000E
           m_scl 00C000
          m_ssl1 00000D
          m_ssl0 00000C
           m_ssl 003000
          m_hpl1 00000B
          m_hpl0 00000A
           m_hpl 000C00
          m_ibl2 000005
          m_ibl1 000004
          m_ibl0 000003
           m_ibl 000038
          m_ial2 000002
          m_ial1 000001
          m_ial0 000000
           m_ial 000007
           m_ipr 00FFFF
           m_rdf 000007
           m_tde 000006
           m_roe 000005
           m_tue 000004
           m_rfs 000003
           m_tfs 000002
           m_if1 000001
           m_if0 000000
            m_if 000002
          m_srie 00000F
          m_stie 00000E
           m_sre 00000D
           m_ste 00000C
           m_mod 00000B
           m_gck 00000A
           m_syn 000009
           m_fsl 000008
          m_sckd 000005
          m_scd2 000004
          m_scd1 000003
          m_scd0 000002
           m_scd 00001C
           m_of1 000001
           m_of0 000000
            m_of 000003
           m_psr 00000F
           m_wl1 00000E
           m_wl0 00000D
            m_wl 006000
            m_dc 001F00
            m_pm 0000FF
           m_tsr 00FFEE
            m_sr 00FFEE
           m_crb 00FFED
           m_cra 00FFEC
            m_tx 00FFEF
            m_rx 00FFEF
           m_tcm 00000F
           m_rcm 00000E
           m_scp 00000D
           m_cod 00000C
            m_cd 000FFF
            m_r8 000007
            m_fe 000006
            m_pe 000005
            m_or 000004
          m_idle 000003
          m_rdrf 000002
          m_tdre 000001
          m_trne 000000
          m_tmie 00000D
           m_tie 00000C
           m_rie 00000B
          m_ilie 00000A
            m_te 000009
            m_re 000008
          m_woms 000007
           m_rwi 000006
          m_wake 000005
           m_sbk 000004
          m_wds2 000002
          m_wds1 000001
          m_wds0 000000
           m_wds 000003
          m_sccr 00FFF2
           m_ssr 00FFF1
           m_scr 00FFF0
          m_stxa 00FFF3
          m_stxh 00FFF6
          m_stxm 00FFF5
          m_stxl 00FFF4
          m_srxh 00FFF6
          m_srxm 00FFF5
          m_srxl 00FFF4
           m_dma 000007
           m_hf1 000004
           m_hf0 000003
            m_hf 000018
           m_hcp 000002
          m_htde 000001
          m_hrdf 000000
           m_hf3 000004
           m_hf2 000003
          m_hcie 000002
          m_htie 000001
          m_hrie 000000
           m_htx 00FFEB
           m_hrx 00FFEB
           m_hsr 00FFE9
           m_hcr 00FFE8
           m_pcd 00FFE5
         m_pcddr 00FFE3
           m_pcc 00FFE1
           m_pbd 00FFE4
         m_pbddr 00FFE2
           m_pbc 00FFE0
           m_bcr 00FFFE
             a1c 0.9914025000
             a1m 0000A2
             a1r 000014
             a1d 006000
             c3c 0.9314831000
             c3m 000539
             c3r 000012
             c3d 005000
             c2c 0.9379399000
             c2m 0004B7
             c2r 000011
             c2d 004800
             c1c 0.9500031000
             c1m 0003C6
             c1r 000010
             c1d 004000
             a2c 0.9970685000
             a2m 000036
             a2r 000015
             a2d 006800
             c4c 0.9273101000
             c4m 00058E
             c4r 000013
             c4d 005800
errors=0
