home *** CD-ROM | disk | FTP | other *** search
- *
- *
- * PITCH.ASM - pitch change effect for TI DSK module.
- *
- *
-
- *
- * Knobs - adjust these values within suggested range for
- * variations on the effect.
- *
- * SWEEP_STEP and UP are set according to the following tables:
- *
- * Semitones Up (UP=1) Down (UP=0)
- * 1 1948 -1839
- * 2 4012 -3575
- * 3 6199 -5213
- * 4 8517 -6760
- * 5 10972 -8219
- * 6 13572 -9597
- * 7 16328 -10897
- * 8 19247 -12125
- * 9 22340 -13284
- * 10 25617 -14377
- * 11 29089 -15409
- * 12 32767 -16384
- *
- * Cents Up (UP=1) Down (UP=0)
- * 2 37 -37
- * 4 75 -75
- * 6 113 -113
- * 8 151 -151
- * 10 189 -188
- * 12 227 -226
- * 14 266 -263
- * 16 304 -301
- * 18 342 -338
- * 20 380 -376
- *
- SWEEP_STEP .set 16328 ; (sets amnt of pitch change, see above tables)
- UP .set 1 ; (0 = down, 1 = up)
- MIX .set 1 ; (0 = no dry, 1 = mix dry signal in)
-
- *
- * Misc. defines
- *
- BUF .set 0420h ; main circular buffer start, middle, and end
- BUF+1 .set 0421h
- BUFMID .set 0500h
- BUFMID+1 .set 0501h
- BUFEND .set 0800h
- BSZ .set 03e0h ; total buffer size
- XFADE .set 508 ; # of samples in crossfade zone
- XMAJOR .set 91 ; fast part of crossfade
- XMINOR .set 38 ; slow part of crossfade
- *
- * Another faster crossfade option, sounds better for certain things
- * XFADE .set 128 ; # of samples in crossfade zone
- * XMAJOR .set 362 ; fast part of crossfade
- * XMINOR .set 150 ; slow part of crossfade
- *
-
- *
- * Data storage
- *
- SWEEPCNT .set 00h ; primary interp factor
- SWEEPCOMP .set 01h ; complement of interp factor
- STEP .set 02h ; inc/dec value for sweepcnt
- TMP .set 03h ; temporary storage reg
- INPVAL .set 04h ; input value
- OUTVAL .set 05h ; output value
- BLENDA .set 06h ; blend for delay A
- BLENDB .set 07h ; blend for delay B
- BL_STEPA .set 08h ; blend step A
- BL_STEPB .set 09h ; blend step B
- ACTIVE_FLG .set 0ah ; active delay channel, 0=delay A, 1=delay B
- SWEEP .set 0bh ; active sweep length
-
- .include "setup.asm"
-
- *
- * main
- *
- main:
- ssxm ; set sign extension mode
- spm 1 ; set P shift for Q15 (1 bit left shift
- ; from P => accum)
- ldpk 8
- lrlk AR0,BUFEND ; permanently point to end of mem buf
- lrlk AR1,BUF ; write ptr, point to start of mem buf
- lrlk AR2,BUF+1 ; delay A 1st read ptr
- lrlk AR3,BUF ; delay A 2nd read ptr
- lrlk AR4,BUFMID+1 ; delay B 1st read ptr
- lrlk AR5,BUFMID ; delay B 2nd read ptr
- lalk 04000h ; half most positive value
- sacl SWEEPCNT ; set initial fractional sweep to midrange val
- lalk 07fffh ; initial blend value for A
- sacl BLENDA
- lack 0 ; initial blend value for B
- sacl BLENDB
- lalk XMINOR ; initial xfade rate for A
- sacl BL_STEPA
- lalk XMAJOR ; initial xfade rate for B
- neg
- sacl BL_STEPB
- ; set amount of pitch change
- lalk SWEEP_STEP ; install sweep rate
- sacl STEP
- abs
- sacl TMP
- ; usable portion of sweep before crossfade
- lt TMP ; |step| * xfade
- mpyk XFADE
- pac
- neg
- sach TMP
- lalk BSZ ; subtract from buffer size
- add TMP
- subk 2 ; just to be sure
- sacl SWEEP ; this is main sweep length counter value
- lar AR6,SWEEP ; load xfade trigger counter
- lark AR7,0 ; this counter is inactive until loaded
- lack 0
- sacl ACTIVE_FLG ; show delay A active first
- lack 014h ; enable AIC recv interrupts
- ldpk 0
- sacl IMR
- ldpk 8
-
- ; loop here forever processing interrupts
- loop: idle
- b loop
-
- *
- * rint
- *
- * Recv interrupt handler performs all the work. Since there is
- * no main thread, there is no need to save or restore regs.
- * We can assume:
- *
- * AR0 - points to end of buffer
- * AR1 - current write ptr
- * AR2 - delay A 1st read ptr
- * AR3 - delay A 2nd read ptr
- * AR4 - delay B 1st read ptr
- * AR5 - delay B 2nd read ptr
- * AR6 - sign counter (indicates when to swap blend signs and reload)
- * AR7 - size counter (indicates when to swap blend step sizes)
- *
- rint:
- ; note: no need to save/restore processor state since
- ; main thread does absolutely nothing
-
- sovm ; set clipping overflow mode for the
- ; "analog" processing
- ldpk 0
- lac DRR ; read in new input value
- ldpk 8
- sfr ; dump 1 junk bit
- .if MIX
- sacl INPVAL ; temporary storage
- .endif
- larp AR1 ; use store ptr AR1
- sacl *+ ; store to circular buffer
- cmpr 0
- bbz nowrap1,*,AR2
- lrlk AR1,BUF
- nowrap1:
-
- ; interpolate A ouput value from the delay A read ptrs
- lalk 32767 ; develop complement of fractional
- sub SWEEPCNT ; sweep position
- sacl SWEEPCOMP
- lt SWEEPCNT ; get fractional sweep position
- mpy *,AR3 ; scale 1st read value
- ltp SWEEPCOMP
- mpy *,AR4 ; scale 2nd read value
- apac
- sach TMP
- ; apply crossfade factor to A
- lt BLENDA
- mpy TMP
- sph TMP ; keep xfaded A val handy
-
- ; interpolate B output value from the delay B read ptrs
- lt SWEEPCNT
- mpy *,AR5 ; scale 1st read value
- ltp SWEEPCOMP
- mpy *,AR2 ; scale 2nd read value
- apac
- sach OUTVAL
- ; apply crossfade factor to B
- lt BLENDB
- mpy OUTVAL
- pac
- addh TMP ; bring in A value
- .if MIX
- addh INPVAL
- .endif
- sach OUTVAL ; this will be our "wet" output value
- lac OUTVAL ; prepare final output for AIC
- andk 0fffch ; clear lowest 2 bits
- ldpk 0
- sacl DXR ; do output
- ldpk 8
-
- ; adjust crossfade blend
- zac
- addh BLENDA ; adjust A crossfade blend
- addh BL_STEPA
- bgez not_neg1 ; clamp at zero
- zac
- not_neg1:
- sach BLENDA
- zac
- addh BLENDB ; adjust B crossface blend
- addh BL_STEPB
- bgez not_neg2,*,AR7 ; clamp at zero
- zac
- not_neg2:
- sach BLENDB
- ; see if size of crossfade steps need changing
- banz chk_ar7,* ; if AR7 == 0, don't decrement (idle)
- b do_sweep,*
- chk_ar7:
- mar *- ; dec AR7
- banz do_sweep,*
- lac BL_STEPA ; simply exchange A and B
- sacl TMP
- lac BL_STEPB
- neg ; but swapping signs to preserve direction
- sacl BL_STEPA
- lac TMP
- neg
- sacl BL_STEPB
-
- ;
- ; now update our sweep stuff
- ;
- do_sweep:
- rovm ; normal overflow operation for arithmetic
- bv next,*,AR2
- next:
-
- .if UP
- ;
- ; UPWARD SWEEP (delay decreasing, pitch goes up)
- ;
- ; always move forward at least one notch
- call inc_delay_ptrs
-
- ; now update fractional delay
- zac ; clear accum
- addh SWEEPCNT ; use high accum for calc
- addh STEP
- sach SWEEPCNT
- bnv done,*,AR2 ; fractional part didn't overflow,
- ; no need to advance sweep further
-
- ; fractional portion overflowed, adjust sweeps A & B forward
- call inc_delay_ptrs
- lac SWEEPCNT ; mask off sign stuff from overflow
- andk 07fffh
- sacl SWEEPCNT
-
- .else
- ;
- ; DOWNWARD SWEEP (delay increasing, pitch goes down)
- ;
- ; see if we need to update pointers
- lac SWEEPCNT
- add STEP ; step is negative here so we're actually
- sacl SWEEPCNT ; subtracting
- blz underflow,*,AR2 ; cnt went less than zero, skip ptr advance
-
- ; no underflow, advance ptrs but skip rest of sweep updates
- call inc_delay_ptrs
- b done,*
-
- ; fractional portion underflowed, update sweep stuff
- underflow:
- lac SWEEPCNT ; mask off sign stuff from underflow
- andk 07fffh
- sacl SWEEPCNT
- .endif
-
- ; see if signs of crossfade steps need changing
- larp AR6
- mar *- ; dec AR6
- banz done,*
- lar AR6,SWEEP ; counter expired, reload
- lac BL_STEPA ; swap signs
- neg
- sacl BL_STEPA
- lac BL_STEPB
- neg
- sacl BL_STEPB
- ; load halfway crossfade counter
- lalk XFADE
- sfr
- sacl TMP
- lrlk AR7,TMP
- ; reset idle delay channel to beginning of sweep by grabbing store ptr
- sar AR1,TMP ; stash store ptr in TMP
- lac ACTIVE_FLG ; see which channel needs restart
- bz reset_B ; A has been active, go reload B
- ; reload delay channel A
- lar AR2,TMP
- lack 0
- sacl ACTIVE_FLG ; indicate A going active
- b done,*
- reset_B:
- ; reload delay channel B
- lar AR4,TMP
- lack 1
- sacl ACTIVE_FLG ; indicate B going active
-
- ;
- ; DONE
- ;
- done:
- eint
- ret
-
-
- *
- * inc_delay_ptrs
- *
- * Increment the both read ptrs for both delays A and B.
- * Must always be called with arp=>AR2.
- *
- inc_delay_ptrs:
- sar AR2,TMP ; copy AR2 to AR3
- lar AR3,TMP
- mar *+ ; inc AR2
- cmpr 0 ; end of buffer?
- bbz nowrap2,*,AR4
- lrlk AR2,BUF ; reload AR2
- nowrap2:
- sar AR4,TMP ; copy AR4 to AR5
- lar AR5,TMP
- mar *+ ; inc AR4
- cmpr 0 ; end of buffer?
- bbz nowrap3,*
- lrlk AR4,BUF ; reload AR4
- nowrap3:
- ret
-
- *
- * tint
- *
- * Timer interrupt - not used.
- *
- tint:
- eint
- ret
-
- *
- * xint
- *
- * AIC xmit interrupt - not used.
- *
- xint:
- eint
- ret
-