home *** CD-ROM | disk | FTP | other *** search
- ; filename: RVB2.ASM
- ;
- ;
- ; This code is an optimized version of the reverberation algorithm
- ; found in file RVB1.ASM. This program makes use of the parallel
- ; move functionality of the 56001. While this tends to make the
- ; code less readible, it does increase its speed. This version
- ; is intended to run on the DSP56000ADSx (Application Development
- ; System)board rev #2, with memory expansion. The memory should
- ; be configured figured for 8K p-memory, 16K x-memory, 8K y-memory.
- ;
- ; Further gains in algorithm speed could be realized on boards not
- ; constrained by the ADS memory limitations. For example, due to
- ; the need for 4 comb filters' worth of storage (each using about
- ; 3500 samples - which takes 4096 samples each after using the DSM
- ; statement) to fit into the 16K available for the x memory, we
- ; must start at address $0000. Thus, we are forced to use all the
- ; 56000's internal memory for sample storage. Without being forced
- ; to start sample storage at $0000, the 56000's internal memory could
- ; be used for coefficient storage, allowing better use of parallel
- ; x and y moves.
- ;
- ; Motorola DSP Group
- ; Austin, Texas
- ;
- ;**************************************************************************
- ; This program was originally available on the Motorola DSP bulletin board
- ; and is provided under a DISCLAIMER OF WARRANTY available from Motorola
- ; DSP Operation, 6501 William Cannon Dr. W Austin, Texas 78735-8598.
- ;**************************************************************************
- ;--------------------------------------------------------------------------
- ; This reverberation program is a variation of the reverberation
- ; system and structures as described by James Moorer's article entitled
- ; 'About this Reverberation Business', Computer Music Journal,
- ; 3(2):13-28, 1979
- ;
- ; Structure is:
- ; .----------.
- ; .------------. .-----. | All Pass |
- ; +->| Comb Filter|-->| SUM |-->| Reverb |
- ; Note: All Comb | | #1 | '-----' | |
- ; Filters | '------------' ^ ^ ^ '----------'
- ; Have a 1st | .------------. | | | |
- ; Order IIR |->| Comb Filter|---+ | | .---V---.
- ; LPF in their | | #2 | | | | align |
- ; feedback | '------------' | | | delay |
- ; loop | .------------. | | '---|---'
- ; |->| Comb Filter|------+ | |
- ; | | #3 | | ----- reverb
- ; | '------------' | \./ gain
- ; | .------------. | |
- ; |->| Comb Filter|---------+ |
- ; | | #4 | |
- ; | '------------' |
- ; | V
- ; .------------. | FIR gain .----------.
- ; | Early | | |\ | |
- ;input -->| Reflection |--+---------| >------------>| summer |--- output
- ; | | FIR | |/ | |
- ; | '------------' '----------'
- ; | ^
- ; | |
- ; | dry gain |
- ; | |\ |
- ; +------------------------------| >----------------+
- ; |/
- ;
- ;.............................................................................
- ; COMB FILTER SUB STRUCTURE:
- ; .-------.
- ; comb i .-----. | long | comb i
- ; input ------>| sum |---->| delay |-------+---------> output
- ; '-----' '-------' |
- ; ^ |
- ; | V
- ; | /| .-----.
- ; +-----< ------------| sum |<--------+
- ; \| '-----' |
- ; fdbck i | / \ lpf i gain
- ; gain V /_____\
- ; gain .----------. |
- ; | 1 sample | |
- ; | delay |-----+
- ; '----------'
- ;.............................................................................
- ; UNIT (ALL PASS) REVERBERATOR STRUCTURE:
- ; based on Schroeder as outlined in Griesinger: 'Practical Processors and
- ; Programs for Digital Reverberation', Audio in Digital Times, 7th AES
- ; conference, Toronto, Ontario, 1989
- ; (the structure outlined in Moorer is a variation of this)
- ;
- ; -g
- ; |\
- ; +---------->| >--------------------------+
- ; | |/ |
- ; | |
- ; | V
- ; unit | .-----. .--------. |\ .-----. unit
- ; input ------+--->| sum |-->| delay |--+--->| >-->| sum |-----> output
- ; '-----' '--------' | |/ '-----'
- ; ^ | 1-g**2
- ; | g |
- ; | /| |
- ; +-----< |---------+
- ; \|
- ;
- ;...........................................................................
- ;
- ; one multi-tap fir structure - to handle early reflections
- ;
- ; followed by 4 parallel comb (iir) filters (each comb having
- ; a first order LPF in its feedback loop
- ;
- ; followed by an 'allpass' reverberator whose output is then
- ; delayed so that its first output follows after the last "early
- ; reflection" output
- ;
- ;__________________________________________________________________________
- ;
- opt cex
- page 132
-
- ;--------------------------------------------------constant declarations
- adc equ $ffef ; ADC address
- dac equ $ffef ; DAC address
-
- ntap equ 7 ; number of taps
- ntapp10 equ ntap+10 ; # taps + 10 for other variables
- tapmod equ ntapp10-1 ; number of taps minus 1
- dlymx equ 4000 ; length of delay line in samples
-
- cmbdly1 equ 2205 ; COMB FILTER CONSTANTS
- cmbdly2 equ 2690 ; delay values (in samples)
- cmbdly3 equ 3175
- cmbdly4 equ 3440
-
- cmbmod1 equ 3490 ; modulo for comb #1 delay line THESE ARE
- cmbmod2 equ 3490 ; " " #2 " " ALSO THE
- cmbmod3 equ 3490 ; " " #3 " " MAX DELAYS
- cmbmod4 equ 3490 ; " " #4 " " ALLOWED FOR
- ; CHOSEN DSM
- ; VALUE
-
- untrvbdly equ 265 ; delay UNIT (or ALLPASS)
- unt_g equ 0.7 ; gains (g) REVERBERATOR
- neg_g equ -unt_g ; (-g)
- one_m_g2 equ (1-unt_g*unt_g) ; " (1-g**2)
-
-
- cmb_g equ 0.86 ; (OVERALL) COMB FILTER FEEDBACK GAIN
- ; controls reverb decay time: smaller
- ; values give quicker decay, larger
- ; values yield slower decay
-
- lpf1 equ 0.408 ; lpf filter coefficient in the
- lpf2 equ 0.448 ; feedback loop of the combs,
- lpf3 equ 0.476 ; these LPF's simulate the high freq
- lpf4 equ 0.496 ; attentuation in real acoustic reverb
-
- fdbck1 equ cmb_g*(1-lpf1) ; actual comb feedback gain
- fdbck2 equ cmb_g*(1-lpf2) ; is determined by the lpf filter
- fdbck3 equ cmb_g*(1-lpf3) ; coefficient and the overall feed-
- fdbck4 equ cmb_g*(1-lpf4) ; back gain to insure stability
-
-
- aligndly equ 1305 ; alignment delay (see diagram above)
- alignmod equ 1390 ; " mod
-
-
- reverbg equ 0.35 ; reverberation output gain value
- firg equ 0.15 ; early rflctn FIR output gain value
- dryg equ 0.9999-(reverbg+firg) ; dry signal gain is rest
- ; CHOOSE THE MIX YOU LIKE
-
-
- org x:0
- chead1 dsm 3500 ; allocates 3500 data spaces for use as
- chead2 dsm 3500 ; comb filter tap delay lines, CHEAD1 refers
- chead3 dsm 3500 ; to the Comb filter HEAD (beginning) for
- chead4 dsm 3500 ; filter #1
-
- org x:$0f00
- ofst_bf dsm ntapp10 ; this reserves "ntap" contiguous addresses
- org x:ofst_bf ; starting at the closest appropriate modulo
- ofst0 dc 1 ; x address space. Then starts filling the
- ofst1 dc 877 ; offset buffer at this location with
- ofst2 dc 1561 ; the right delay values for the
- ofst3 dc 1716 ; EARLY REFLECTION FIR
- ofst4 dc 1826
- ofst5 dc 3083 ; IMPORTANT - to get no delay for the first
- ofst6 dc 3510 ; early reflection, use a "1". This is due the use
- ; of an instruction code pre-decrement, a "0" value
- ; will cause a maximum delay equal to the tap delay
- ; line length
-
- untdly dc untrvbdly ; define the UNIT REVERBERATOR delay
- untmod dc untrvbdly-1 ; modulo for " "
-
- algndly dc aligndly
- algnmod dc alignmod
-
- org y:$0f00
- gain_bf dsm ntapp10
- org y:gain_bf ; starting at y address zero this reserves
- ; "ntap" contiguous addresses then starts
- ; filling these addresses with the desired
- gain0 dc 0.213 ; tap "gain" values for EARLY REFLECTION FIR
- gain1 dc 0.217 ; recommended by moorer
- gain2 dc 0.174 ;
- gain3 dc 0.135 ; it is recommended to keep many early
- gain4 dc 0.153 ; reflection returns, as these are fed into
- gain5 dc 0.157 ; comb filters, than can contribute greatly
- gain6 dc 0.051 ; to the later impulse response density
- c1g2 dc fdbck1
- c2g2 dc fdbck2
- c3g2 dc fdbck3
- c4g2 dc fdbck4
- c1out ds 1
- untg2 dc neg_g
- untg3 dc one_m_g2
- untg1 dc unt_g
- firgain dc firg
- drygain dc dryg
- rvbgain dc reverbg
-
- org y:0
- c1g1 dc lpf1 ; comb #1 g1 (LPF gain)
- c2g1 dc lpf2 ; #2
- c3g1 dc lpf3 ; #3
- c4g1 dc lpf4 ; #4
-
-
- sample ds 1 ; input sample storage address
- firout ds 1 ; early ref FIR OUTput storage address
-
- ; COMB filter output storage address
- c2out ds 1 ; " " #2 " " "
-
- lpfst1 ds 1 ; " " #1 Low Pass Filter state
- lpfst2 ds 1 ; " " #2 " " " "
- lpfst3 ds 1 ; " " #3 " " " "
- lpfst4 ds 1 ; " " #4 " " " "
-
- ; allocates modulo memory for the unit
- udlyln dsm 300 ; (allpass) reverberator delay line
-
- algndlyln dsm 1400 ; allocates modulo memory for alignment delay
- ; line
-
- dlyline dsm dlymx ; allocates mod memory for the FIR delay line
-
- ;--------------------------------------------------------------------------
- org p:$40 ; program start address
-
- ; Set up ADS board in case of force break instead of force reset
- movep #0,x:$FFFE ;set bcr to zero
- movec #0,sp ;init stack pointer
- movec #0,sr ;clear loop flag
-
- ; Set up the SSI for operation with the DSP56ADC16EVB
- ; The following code sets port C to function as SCI/SSI
- move #$0,a0 ;zero PCC to cycle it
- movep a0,x:$FFE1
- move #$0001ff,a0
- movep a0,x:$FFE1 ;write PCC
-
- ; The following code sets the SSI CRA and CRB control registers for external
- ; continuous clock, synchronous, normal mode.
- move #$004000,a0 ;CRA pattern for word length=16 bits
- movep a0,x:$FFEC
- move #$003200,a0 ;CRB pattern for continous ck,sych,normal mode
- movep a0,x:$FFED ;word long frame sync: FSL=0;ext ck/fs
-
- ; -------------------------------------------------------------------------
- ; initialize registers MO,RO, etc
- move #dlymx-1,m0 ; tap line modulus
- move #dlyline,r0 ; start of delay line
- move #0,n0 ;
-
- move #tapmod,m1 ; tap gain line modulo
- move #gain_bf,r1 ; tap gain & tap delay pointer
-
- move #cmbmod1,m2 ; initialize the modulo registers
- move #cmbmod2,m3 ; for comb filter buffers 1 thru 5
- move #cmbmod3,m4
- move #cmbmod4,m5
-
- move #cmbdly1,n2 ; initialize the offset register
- move #cmbdly2,n3 ; for Comb filters 1 thru 5
- move #cmbdly3,n4
- move #cmbdly4,n5
-
- move #chead1,r2 ; initialize the pointer values for
- move #chead2,r3 Comb filters 1 thru 5
- move #chead3,r4
- move #chead4,r5
-
- move x:algnmod,m6 ; initialize alignment delay line
- move x:algndly,n6 ; offset, modulo, and pointer registers
- move #algndlyln,r6
-
- move x:untmod,m7 ; initialize unit reverberator (allpass)
- move x:untdly,n7 ; offset, modulo, and pointer registers
- move #udlyln,r7
-
- ;---------------------------------------------------------------------------
- ; The following code polls the RDF flag in the SSI-SR and waits for RDF=1
- ; and then reads the RX register to retrieve the data from the A/D converter.
- ; Sample rate is controlled by DSP56ADC16 board.
-
- poll jclr #7,x:$FFEE,poll ;loop until RDF bit = 1
- movep x:adc,a ;get A/D converter data
- ;---------------------------------------------------------------------------
- asr a
- asr a ; obtain data sample
- ; and shift right for headroom
- move a,y:sample ; keep dry sample
-
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- ; FIR for early reflections
- move a,y:(r0)- ; push sample into delay line
- clr a x:(r1),n0 ; clr A and load offset into N0
- do #ntap,fir ; loop over the (ntaps-1),exclude fb tap now
- move y:(r1)+,y1 ; " " " gain " " Y
- move y:(r0+n0),x1 ; get delayed sample
- mac x1,y1,a x:(r1),n0 ; MAC gain and sample & update offset
- fir move a,y:firout ; save FIR OUTput to y memory
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- ; COMB 1
- move x:(r2+n2),b ; get delayed sample & put in b
- move b,y:c1out ; move output to y memory space
-
- move y:c1g1,x1 ; get LPF filter coeff
- move y:lpfst1,y1 ; get LPF filter state
- mac x1,y1,b y:(r1)+,x1 ; compute LPF output
- move b,y:lpfst1 ; save LPF output to LPF state
-
- move b,y1 ; put LPF output in Y1
- mac x1,y1,a x:(r3+n3),b ; compute feedback term in A
- move a,x:(r2)- ; store output into delay queue
-
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- ; COMB 2
- move y:firout,a ; comb filter #1 with LPF in feed back
- move b,y:c2out ; move output to y memory space
-
- move y:c2g1,x1 ; get LPF filter coeff
- move y:lpfst2,y1 ; get LPF filter state
- mac x1,y1,b y:(r1)+,x1 ; compute LPF output
- move b,y:lpfst2 ; save LPF output to LPF state
-
- move b,y1 ; put LPF output in Y1
- mac x1,y1,a x:(r4+n4),b ; compute feedback term in A
- move a,x:(r3)- ; store output into delay queue
-
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- ; COMB 3
- move y:firout,a ; comb filter #1 with LPF in feed back
- move b,x0
-
- move y:c3g1,x1 ; get LPF filter coeff
- move y:lpfst3,y1 ; get LPF filter state
- mac x1,y1,b y:(r1)+,x1 ; compute LPF output
- move b,y:lpfst3 ; save LPF output to LPF state
-
- move b,y1 ; put LPF output in Y1
- mac x1,y1,a x:(r5+n5),b ; compute feedback term in A
- move a,x:(r4)- ; store output into delay queue
- ; - - - - - - - - - - - - - - - - -
- ; COMB 4
- move y:firout,a ;
- move b,y0
-
- move y:c4g1,x1 ; get LPF filter coeff
- move y:lpfst4,y1 ; get LPF filter state
- mac x1,y1,b y:(r1)+,x1 ; compute LPF output
- move b,y:lpfst4 ; save LPF output to LPF state
-
- move b,y1 ; put LPF output in Y1
- mac x1,y1,a y:(r1)+,x1 ; compute feedback term in A,c1out to x1
- move a,x:(r5)- ; store output into delay queue
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- move y:c2out,a ; add output of add four combs
- add x1,a ; c2out + c1out
- add x0,a y:(r7+n7),x0 ; +c3out
- add y0,a y:(r1)+,y1 ; +c4out
-
- ; asr a
- ; - - - - - - - - - - - - - - - - - -
- ; all pass unit reverberator
- move a,x1
- mpy x1,y1,b y:(r1)+,y1
-
- mac x0,y1,b y:(r1)+,y1 ; MAC into b for output (B CONTAINS OUTPUT)
- move b,y:(r6)-
-
- mac x1,y1,a y:(r6+n6),y1
- move a,y:(r7)- ; put new+g*delayed into delay line/inc r7
- ; - - - - - - - - - - - - -
- move y:rvbgain,y0
- mpy y1,y0,a y:(r1)+,x1
-
- move y:firout,y1
- mac x1,y1,a y:(r1)+,x1
-
- move y:sample,y1 ; mix in the dry sample
- mac x1,y1,a ; A now contains the output sample
- asr a
- ; - - - - - - - - - - - - - - - - - - - - - - - -
- ; Write DSP56ADC16 A/D converter data to the PCM-56
-
- move a,x:dac ;write the PCM-56 D/A via SSI xmt reg.
- jmp poll ;loop indefinitely
-
- end
-