このアプリケーションノートは、オーディオフィルタについての簡単な実例を取り上げています。オーディオデータは、「The pipe began to rust while new.」という、あらかじめ録音した著者のメッセージです。このテキストは、無作為に選んだものではありません。各周波数成分が適度に組み合わされており、単純なフィルタの可聴効果を強調することのできるテキストです(http://www.cs.columbia.edu/~hgs/audio/harvard.html)。このオーディオ録音は、適当な長さの8kHzの録音で代用することができます(必須ではありません)。
move MCNT, #22h ; signed, mult-accum, clear regs first
zeroes_filterloop:
move A[0], DP[0] ; let's see if we are out of data
cmp #W:rawaudiodata ; compare to the start of the audio data
lcall UROM_MOVEDP1INC ; get next filter coefficient
move MA, GR ; multiply filter coefficient...
lcall UROM_MOVEDP0DEC ; get next filter data
move MB, GR ; multiply audio sample...
jump e, zeroes_outofdata ; stop if at the start of the audio data
djnz LC[0], zeroes_filterloop
zeroes_outofdata:
move A[2], MC2 ; get MAC result HIGH
move A[1], MC1 ; get MAC result MID
move A[0], MC0 ; get MAC result LOW
zeroes_filterloop:
move A[0], DP[0] ; 1, let's see if we are out of data
cmp #W:rawaudiodata ; 2, compare to the start of the audio data
move DP[1], DP[1] ; 1, select DP[1] as our active pointer
move GR, @DP[1]++ ; 1, get next filter coefficient
move MA, GR ; 1, multiply filter coefficient...
move BP, BP ; 1, select BP[Offs] as our active pointer
move GR, @BP[Offs--] ; 1, get next filter data
move MB, GR ; 1, multiply audio sample...
jump e, zeroes_outofdata ; 1, stop if at the start of the audio data
djnz LC[0], zeroes_filterloop ; 1
zeroes_filterloop:
move A[0], DP[0] ; 1, let's see if we are out of data
cmp #W:rawaudiodata ; 2, compare to the start of the audio data
move DP[1], DP[1] ; 1, select DP[1] as our active pointer
move MA, @DP[1]++ ; 1, multiply next filter coefficient
move BP, BP ; 1, select BP[Offs] as our active pointer
move MB, @BP[Offs--] ; 1, multiply next filter data
jump e, zeroes_outofdata ; 1, stop if at the start of the audio data
djnz LC[0], zeroes_filterloop ; 1
move A[2], MC2 ; get MAC result HIGH
move A[1], MC1 ; get MAC result MID
move A[0], MC0 ; get MAC result LOW
move APC, #0C2h ; clear AP, roll modulo 4, auto-dec AP
shift_loop:
;
; Because we use fixed point precision, we need to shift to get a real
; sample value. This is not as efficient as it could be. If we had a
; dedicated filter, we might make use of the shift-by-2 and shift-by-4
; instructions available on MAXQ.
;
move AP, #2 ; select HIGH MAC result
move c, #0 ; clear carry
rrc ; shift HIGH MAC result
rrc ; shift MID MAC result
rrc ; shift LOW MAC result
djnz LC[1], shift_loop ; shift to get result in A[0]
move APC, #0 ; restore accumulator normalcy
move AP, #0 ; use accumulator 0
;
; don't care about high word, since we shift left and take the
; middle word.
;
move A[1], MC1 ; 1, get MAC result MID
move A[0], MC0 ; 1, get MAC result LOW
move MCNT, #20h ; 1, clear the MAC, multiply mode only
move AP, #0 ; 1, use accumulator 0
and #0F000h ; 2, only want the top 4 bits
move MA, A[0] ; 1, lower word first
move MB, #10h ; 1, multiply by 2^4
move A[0], MC1R ; 1, get the high word, only lowest 4 bits significant
move MA, A[1] ; 1, now the upper word, we want lowest 12 bits
move MB, #10h ; 1, multiply by 2^4
or MC1R ; 1, combine the previous result and this one
;
; result is in A[0]
;