?? ad_pcm.asm
字號(hào):
* 編碼函數(shù)C語言聲明
* extern void AdpcmEncoder(int* pBufferIn, int* pBufferOut,
* int* pPrevValue,int* pPrevIndex, int Length);
* 解碼函數(shù)C語言聲明(解碼長(zhǎng)度為實(shí)際解碼后長(zhǎng)度的1/4)
* extern void AdpcmDecoder(int* pBufferIn, int* pBufferOut,
* int* pPrevValue,int* pPrevIndex, int Length);
*
* 編解碼后的PrevValue和PrevIndex都被修改,在后續(xù)的編解碼中將繼續(xù)被使用
*
* CCS2.1下測(cè)試通過
.title "Intel/DVI ADPCM coder/decoder"
.def _AdpcmEncoder
.def _AdpcmDecoder
.mmregs
;索引表
.data
IndexTable: ; 實(shí)際上只用了15個(gè),考慮到速度問題,有一個(gè)舍棄了
.word -8, -5, -3, -1, 1, 3, 5, 8
.word 8, 5, 3, 1, -1,-3,-5,-8
;步進(jìn)量
StepSizeTable: ; 共84個(gè)
.word 4, 5, 6, 7, 8, 9, 10, 11, 12, 14
.word 16, 18, 20, 22, 25, 28, 32, 36, 42, 49
.word 57, 67, 78, 90, 103, 118, 134, 152, 170, 189
.word 209, 230, 253, 279, 307, 337, 371, 408, 449, 494
.word 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282
.word 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327
.word 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630
.word 9493, 10442, 11487, 12635,13899, 15289,16818, 18500, 20350, 22385
.word 24623, 27086, 29794, 32767
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 寄存器使用規(guī)則(調(diào)用時(shí)不設(shè)置)
; AR0: 臨時(shí)變量
; AR2: 輸入緩沖區(qū)指針
; AR3: 輸出緩沖區(qū)指針
; AR4: 步進(jìn)量地址指針
; AR5: 當(dāng)前輸出數(shù)據(jù)計(jì)數(shù)器(0--3: 16位長(zhǎng)度可保存4個(gè)編碼數(shù)據(jù))
.asg *SP(3), pBufferOut
.asg *SP(4), pPrevValue
.asg *SP(5), pPrevIndex
.asg *SP(6), Length
.asg *SP(0), PrevValue ; 占用了這兩個(gè)堆棧位置,存放臨時(shí)數(shù)據(jù)
.asg *SP(1), PrevIndex ;
.text
_AdpcmEncoder:
TC = (*SP(4) == #0) ; 首先檢測(cè)緩沖區(qū)長(zhǎng)度是否為0,為0則結(jié)束
if(TC) dgoto EncoderEnd
AR5 = #4 ; 設(shè)置計(jì)數(shù)器初值
SP += -2 ; 調(diào)整堆棧指針,以便利用其中的兩個(gè)子
AR2 = A ; 讀取輸入緩沖區(qū)地址
B = pBufferOut ; 讀入輸出緩沖區(qū)地址
AR3 = B
B = pPrevValue ; 讀入上次轉(zhuǎn)換值地址
AR0 = B
ASM = #0
SXM = 1 ; 設(shè)置符號(hào)位擴(kuò)展
Length -= 1 ; 長(zhǎng)度減1
A = pPrevIndex ; 讀取上次轉(zhuǎn)換的索引
B = *AR0
AR0 = A
PrevValue = B ; 讀取上次轉(zhuǎn)換值
FRCT = 0
A = *AR0
PrevIndex = A ; 保存上次轉(zhuǎn)換索引
A = Length ; 讀取轉(zhuǎn)換長(zhǎng)度
BRC = A ; 設(shè)置塊循環(huán)計(jì)數(shù)器
A = PrevIndex
DBLOCKREPEAT(EncoderLoopEnd-1) ; 啟動(dòng)塊循環(huán)(根據(jù)循環(huán)最后一條指令確定是1還是2)
*AR3 = #0 ; 輸出緩沖區(qū)第一個(gè)字清零
EncoderLoop:
A += #StepSizeTable ; 偏移
AR4 = A ; 取得步進(jìn)基地址 + 偏移
B = *AR2+ ; 取得輸入緩沖區(qū)的值(沒有必要規(guī)范到-32768...+32767)
B -= PrevValue ; 獲得當(dāng)前值與上次計(jì)算值之間的差值
A = |B| ; 計(jì)算delta=diff/step,并將商規(guī)范到-8...+7
REPEAT(#16) ; 循環(huán)減(做除法)多除了一次,相當(dāng)于商×2
SUBC(*AR4, A)
A += #1 ; 調(diào)整0.5的差值
A &= #0FFFFh ; (清除高位無效數(shù)據(jù))
A = A >> 1
if(BGEQ) DGOTO EncoderSetDelta ; 檢測(cè)是否是負(fù)數(shù)
B = #7 ; 將Delta數(shù)據(jù)規(guī)范到-8...+7
A = MIN(A, B)
A = -A ; 是負(fù)數(shù),商取負(fù)
EncoderSetDelta:
;B = #-8 ; 已經(jīng)規(guī)范到0--7了,取負(fù)數(shù)后也沒有關(guān)系
;A =MAX(A, B)
T = A
; 計(jì)算PrevValue值,并將其規(guī)范到(-32768)--(+32767)
B = T*(*AR4) ; 獲得Delta*Step的值,保存在B寄存器中
B += PrevValue ; 計(jì)算上次值與這次差值的和
;B += *AR4 >> 1
B = B <<C 8 ; 只有32位的飽和運(yùn)算
B = B <<C 8 ; 移位操作比用max/min指令要快
saturate(B) ; 飽和成32位的數(shù)據(jù)
; 檢測(cè)是否需要將輸出指針移動(dòng)到下一個(gè)字
if(*AR5- != 0) DGOTO EncoderNoInc
A &= #0Fh ; 保留低4位
AR5 = #3 ; 重新設(shè)置計(jì)數(shù)器
*+AR3 = #0 ; 輸出緩沖區(qū)清零
EncoderNoInc:
PrevValue = hi(B) ; 保存當(dāng)前轉(zhuǎn)換結(jié)果
B = A + *AR3 << 4 ; 將輸出緩沖區(qū)當(dāng)前字左移4位,然后加上當(dāng)前值
*AR3 = B ;
AR0 = A ; 取得更新后的索引
B = #0
A = PrevIndex
A += *AR0(IndexTable) ; 基地址 + 偏移
A = MAX(A, B) ; 將PrevIndex規(guī)范到0-83
B = #83
A = MIN(A, B)
PrevIndex = A
EncoderLoopEnd:
B = pPrevValue ; 設(shè)置轉(zhuǎn)換后的PrevIndex和PrevValue
AR0 = B
A = pPrevIndex
AR2 = A
A = PrevIndex
B = PrevValue
*AR2 = A
SP += 2 ; 將堆棧指針調(diào)整回原來的值
*AR0 = B
NOP ; 避免沖突用的
EncoderEnd:
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 寄存器使用規(guī)則(調(diào)用時(shí)不設(shè)置)
; AR0: 臨時(shí)變量
; AR1: 當(dāng)前轉(zhuǎn)換值
; AR2: 輸入緩沖區(qū)指針
; AR3: 輸出緩沖區(qū)指針
; AR4: 步進(jìn)量地址指針
; AR5: 當(dāng)前輸出數(shù)據(jù)計(jì)數(shù)器(0--3: 16位長(zhǎng)度可保存4個(gè)編碼數(shù)據(jù))
.asg *SP(3), StepValue ; 臨時(shí)變量,存放當(dāng)前的輸入處理值(不斷左移4位)
_AdpcmDecoder:
TC = (*SP(4) == #0)
if(TC) DGOTO DecoderEnd ; 如果長(zhǎng)度為0,退出
AR5 = #3 ; 設(shè)置循環(huán)計(jì)數(shù)器
SP -= 2 ; 調(diào)整堆棧指針,以便有多余的兩個(gè)字可供臨時(shí)使用
AR2 = A ; 取輸入緩沖區(qū)地址
A = pBufferOut ; 取輸出緩沖區(qū)地址
B = pPrevValue ; 取存放上次轉(zhuǎn)換值變量的地址
AR0 = B
ASM = #0 ; (好像沒有用)
SXM = 1 ; 設(shè)置符號(hào)位擴(kuò)展
AR3 = A ; 取得輸出緩沖區(qū)
B= *AR0 ; 取得PrevValue
A = pPrevIndex ; 取PrevIndex的地址
AR0 = A ; 臨時(shí)存放地址(直接存會(huì)出錯(cuò)(編譯得就不對(duì)))
PrevValue = B ; 呵呵,終于取出來了
OVM = 1 ; 溢出吧,我的兄弟,就等你了
A = *AR0 ; 讀取PrevIndex的值
PrevIndex = A
A = Length<<2 ; 因?yàn)槭?6位操作,可存放4個(gè)轉(zhuǎn)換值,乘以4
A -= #1 ; 減去1,循環(huán)次數(shù)要比實(shí)際次數(shù)少1
BRC = A ; 設(shè)置塊循環(huán)計(jì)數(shù)器
A = *AR2+ ; 取輸入緩沖區(qū)的值
DBLOCKREPEAT(DecoderLoopEnd-1) ; 運(yùn)轉(zhuǎn)起來吧,要不然飯都涼了
StepValue = A ; 獲得當(dāng)前處理值
A = PrevIndex ; 取得當(dāng)前index所對(duì)應(yīng)的值
DecoderLoop:
A += #StepSizeTable
AR4 = A
A = StepValue << 4 ; 取當(dāng)前轉(zhuǎn)換值,獲得delta值(利用了符號(hào)擴(kuò)展功能)
StepValue = A
B = PrevValue
B = B + hi(A)*(*AR4) ; 獲得計(jì)算的差值
;B += *AR4 >> 1
B = B <<C 8 ; 因?yàn)橹荒苓M(jìn)行32位的飽和運(yùn)算,沒有辦法啦
B = B <<C 8 ; 將數(shù)據(jù)規(guī)范到-32768...+32767
saturate(B)
if(*AR5- != 0) DGOTO DecoderNoInc
*AR3+ = hi(B)
PrevValue = hi(B)
AR5 = #3 ; 重新設(shè)置計(jì)數(shù)器
B = *AR2+
StepValue = B
DecoderNoInc:
A = A >> 16 ; 調(diào)整PrevIndex的值
A &= #0Fh ; 并將其調(diào)整在0...83之間
AR0 = A
B = #0
A = PrevIndex
A += *AR0(IndexTable)
A = MAX(A, B)
B = #83
A = MIN(A, B)
PrevIndex = A
DecoderLoopEnd:
B = pPrevValue ; 設(shè)置PrevValue和PrevIndex
AR0 = B
B = PrevValue
A = pPrevIndex
AR2 = A
A = PrevIndex
*AR0 = B
*AR2 = A
SP += 2 ; 將堆棧指針調(diào)整回原來的值
NOP ; 避免沖突用的
DecoderEnd:
RETURN
.end
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -