📄 adpcm.asm
字号:
cblock <StartAddress>
PrevSampleL
PrevSampleH
PrevIndex
DiffL
DiffH
StepL
StepH
PredSampleL
PredSampleH
PredSampleU
DiffqL
DiffqH
Index
SampleL
SampleH
Code
endc
;**********************************************************************
;* Table of index changes
;**********************************************************************
IndexTable
addwf PCL,F
dt 0xff,0xff,0xff,0xff,2,4,6,8,0xff,0xff,0xff,0xff,2,4,6,8
;**********************************************************************
;* Quantizer step size lookup table
;**********************************************************************
StepSizeTable
addwf PCL,F
dt 0x07,0x00,0x08,0x00,0x09,0x00,0x0A,0x00,0x0B,0x00,0x0C,0x00,0x0D
dt 0x00,0x0E,0x00,0x10,0x00,0x11,0x00,0x13,0x00,0x15,0x00,0x17,0x00
dt 0x19,0x00,0x1C,0x00,0x1F,0x00,0x22,0x00,0x25,0x00,0x29,0x00,0x2D
dt 0x00,0x32,0x00,0x37,0x00,0x3C,0x00,0x42,0x00,0x49,0x00,0x50,0x00
dt 0x58,0x00,0x61,0x00,0x6B,0x00,0x76,0x00,0x82,0x00,0x8F,0x00,0x9D
dt 0x00,0xAD,0x00,0xBE,0x00,0xD1,0x00,0xE6,0x00,0xFD,0x00,0x17,0x01
dt 0x33,0x01,0x51,0x01,0x73,0x01,0x98,0x01,0xC1,0x01,0xEE,0x01,0x20
dt 0x02,0x56,0x02,0x92,0x02,0xD4,0x02,0x1C,0x03,0x6C,0x03,0xC3,0x03
dt 0x24,0x04,0x8E,0x04,0x02,0x05,0x83,0x05,0x10,0x06,0xAB,0x06,0x56
dt 0x07,0x12,0x08,0xE0,0x08,0xC3,0x09,0xBD,0x0A,0xD0,0x0B,0xFF,0x0C
dt 0x4C,0x0E,0xBA,0x0F,0x4C,0x11,0x07,0x13,0xEE,0x14,0x06,0x17,0x54
dt 0x19,0xDC,0x1B,0xA5,0x1E,0xB6,0x21,0x15,0x25,0xCA,0x28,0xDF,0x2C
dt 0x5B,0x31,0x4B,0x36,0xB9,0x3B,0xB2,0x41,0x44,0x48,0x7E,0x4F,0x71
dt 0x57,0x2F,0x60,0xCE,0x69,0x62,0x74,0xFF,0x7F
;**********************************************************************
;* ADPCMEncoder - ADPCM encoder routine
;* The sample to be encoded is loaded into SampleH:SampleL before
;* calling this routine.
;**********************************************************************
ADPCMEncoder
bcf STATUS,RP0
; Restore prev values of predicted sample & quantizer step size index
movf PrevSampleL,W ;predsample = state.prevsample;
movwf PredSampleL
movf PrevSampleH,W
movwf PredSampleH
movlw 0xFF
movwf PredSampleU
btfss PredSampleH,7
clrf PredSampleU,F
movf PrevIndex,W ;index = state.previndex;
movwf Index
movf Index,W ;step = StepSizeTable[index];
movwf FSR
bcf STATUS,C
rlf FSR,F
movlw 0x00
movwf PCLATH
movf FSR,W
call StepSizeTable
bcf STATUS,RP0
movwf StepL
incf FSR,F
movlw 0x00
movwf PCLATH
movf FSR,W
call StepSizeTable
bcf STATUS,RP0
movwf StepH
; Compute difference between the acutal sample and the predicted sample
movf PredSampleL,W ;diff = sample - predsample;
subwf SampleL,W
movwf DiffL
movf PredSampleH,W
btfss STATUS,C
addlw 0x01
subwf SampleH,W
movwf DiffH
btfsc DiffH,7 ;if(diff >= 0)
goto EInvertDiff
clrf Code ; code = 0;
goto EQuantize ;else
EInvertDiff ;{
movlw 0x08 ; code = 8;
movwf Code
comf DiffH,F ; diff = -diff;
comf DiffL,F
incf DiffL,F
btfss STATUS,Z
goto EQuantize
bcf STATUS,RP0
incf DiffH,F ;}
; Quantize diff into 4-bit ADPCM code using the quantizer step size &
; Inverse quantize into predicted diff using quantizer step size
EQuantize
bcf STATUS,RP0 ;diffq = step >> 3;
movf StepL,W
movwf DiffqL
movf StepH,W
movwf DiffqH
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
movf StepL,W ;if( diff >= step )
subwf DiffL,W :{
movlw 0x80
xorwf DiffH,W
movwf 29
movlw 0x80
xorwf StepH,W
btfss STATUS,C
addlw 0x01
subwf 29,W
btfss STATUS,C
goto ECode2
bcf STATUS,RP0 ; code |= 4;
bsf Code,2
movf StepL,W ; diff -= step;
subwf DiffL,F
movf StepH,W
btfss STATUS,C
addlw 0x01
subwf DiffH,F
movf StepL,W ; diffq += step;
addwf DiffqL,F
movf StepH,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F ;}
ECode2
bcf STATUS,RP0 ;step >>= 1;
rlf StepH,W
rrf StepH
rrf StepL
movf StepL,W ;if( diff >= step )
subwf DiffL,W ;{
movlw 0x80
xorwf DiffH,W
movwf 29
movlw 0x80
xorwf StepH,W
btfss STATUS,C
addlw 0x01
subwf 29,W
btfss STATUS,C
goto ECode1
bcf STATUS,RP0 ; code |= 2;
bsf Code,1
movf StepL,W ; diff -= step;
subwf DiffL,F
movf StepH,W
btfss STATUS,C
addlw 0x01
subwf DiffH,F
movf StepL,W ; diffq += step;
addwf DiffqL,F
movf StepH,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F ;}
ECode1
bcf STATUS,RP0 ;step >>= 1;
rlf StepH,W
rrf StepH,F
rrf StepL,F
movf StepL,W ;if( diff >= step )
subwf DiffL,W ;{
movlw 0x80
xorwf DiffH,W
movwf 29
movlw 0x80
xorwf StepH,W
btfss STATUS,C
addlw 0x01
subwf 29,W
btfss STATUS,C
goto ENewPredict
bcf STATUS,RP0 ; code |= 1;
bsf Code,0
movf StepL,W ; diffq += step;
addwf DiffqL
movf StepH,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F ;}
; Fixed predictor computes new predicted sample by adding the old predicted sample
; to predicted difference
ENewPredict
bcf STATUS,RP0 ;if( code & 8 )
btfss Code,3
goto EAddDiff
movf DiffqL,W ; predsample -= diffq;
subwf PredSampleL,F
movf DiffqH,W
btfss STATUS,C
addlw 0x01
subwf PredSampleH,F
clrw
btfss STATUS,C
addlw 0x01
subwf PredSampleU,F
goto EOverflow
EAddDiff ;else
movf DiffqL,W ; predsample += diffq;
addwf PredSampleL
movf DiffqH,W
btfsc STATUS,C
addlw 0x01
addwf PredSampleH,F
clrw
btfsc STATUS,C
addlw 0x01
addwf PredSampleU,F
; Check for overflow of the new predicted sample
EOverflow
movf PredSampleU,F ;if( predsample > 32767 )
btfss STATUS,Z
goto ECheckNeg
btfss PredSampleH,7
goto ECheckNeg
movlw 0xFF ; predsample = 32767;
bcf STATUS,RP0
movwf PredSampleL
movlw 0x7F
movwf PredSampleH
goto ENewIndex
ECheckNeg ;else if( predsample < -32768)
incf PredSampleU,W
btfss STATUS,Z
goto ENewIndex
btfsc PredSampleH,7
goto ENewIndex
bcf STATUS,RP0 ; predsample = -32768
clrf PredSampleL
movlw 0x80
movwf PredSampleH
; Find new quantizer stepsize index by adding old index to table lookup
; using the ADPCM code
ENewIndex
clrf PCLATH ;index += IndexTable[code];
bcf STATUS,RP0
movf Code,W
call IndexTable
bcf STATUS,RP0
addwf Index,F
; Check for overflow of the new quantizer step size index
btfsc Index,7 ;if( index < 0 )
clrf Index ; index = 0;
movlw 0x80 ;if( index > 88 )
xorwf Index,W
movwf 21
movlw 0xD8
subwf 21,W
btfss STATUS,Z
btfss STATUS,C
goto ESave
movlw 0x58 ; index = 88;
bcf STATUS,RP0
movwf Index
; Save predicted sample & quantizer step size index for next iteration
ESave
bcf STATUS,RP0 ;state.prevsample = predsample;
movf PredSampleL,W
movwf PrevSampleL
movf PredSampleH,W
movwf PrevSampleH
movf Index,W ;state.previndex = index;
movwf PrevIndex
; ADPCM code is in the register Code
return ;}
;**********************************************************************
;* ADPCMDecoder - ADPCM decoder routine
;* The ADPCM code to decode is stored in the register Code before
;* calling this routine.
;**********************************************************************
ADPCMDecoder ;{
bcf STATUS,RP0
; Restore prev values of predicted sample & quantizer step size index
movf PrevSampleL,W ;predsample = state.prevsample;
movwf PredSampleL
movf PrevSampleH,W
movwf PredSampleH
movlw 0xFF
movwf PredSampleU
btfss PredSampleH,7
clrf PredSampleU,F
movf PrevIndex,W ;index = state.previndex;
movwf Index
; Find quantizer step size from lookup table using index
movf Index,W ;step = StepSizeTable[index];
movwf FSR
bcf STATUS,C
rlf FSR,F
movlw 0x00
movwf PCLATH
movf FSR,W
call StepSizeTable
bcf STATUS,RP0
movwf StepL
incf FSR,F
movlw 0x00
movwf PCLATH
movf FSR,W
call StepSizeTable
bcf STATUS,RP0
movwf StepH
; Inverse quantize ADPCM code into diff using the quantizer step size
movf StepL,W ;diffq = step >> 3;
movwf DiffqL
movf StepH,W
movwf DiffqH
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
rlf DiffqH,W
rrf DiffqH,F
rrf DiffqL,F
btfss Code,2 ;if( code & 4 )
goto DCode2
movf StepL,W ; diffq += step;
addwf DiffqL
movf StepH,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F
DCode2
btfss Code,1 ;if( code & 2 )
goto DCode1
movf StepL,W ; diffq += step >> 1;
movwf 28
movf StepH,W
movwf 29
rlf 29,W
rrf 29
rrf 28
movf 28,W
addwf DiffqL
movf 29,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F
DCode1
btfss Code,0 ;if( code & 1 )
goto DNewPredict
movf StepL,W ; diffq += step >> 2;
movwf 28
movf StepH,W
movwf 29
rlf 29,W
rrf 29
rrf 28
rlf 29,W
rrf 29
rrf 28
movf 28,W
addwf DiffqL,F
movf 29,W
btfsc STATUS,C
addlw 0x01
addwf DiffqH,F
; Add the difference to the predicted sample
DNewPredict
btfss Code,3 ;if( code & 8 )
goto DAddDiff
movf DiffqL,W ; predsample -= diffq;
subwf PredSampleL,F
movf DiffqH,W
btfss STATUS,C
addlw 0x01
subwf PredSampleH,F
clrw
btfss STATUS,C
addlw 0x01
subwf PredSampleU,F
goto DOverflow
DAddDiff ;else
movf DiffqL,W ; predsample += diffq;
addwf PredSampleL
movf DiffqH,W
btfsc STATUS,C
addlw 0x01
addwf PredSampleH,F
clrw
btfsc STATUS,C
addlw 0x01
addwf PredSampleH,F
; Check for overflow of the new predicted sample
DOverflow
movf PredSampleU,F ;if( predsample > 32767 )
btfss STATUS,Z
goto DCheckNeg
btfss PredSampleH,7
goto DCheckNeg
movlw 0xFF ; predsample = 32767;
bcf STATUS,RP0
movwf PredSampleL
movlw 0x7F
movwf PredSampleH
goto DNewIndex
DCheckNeg ;else if( predsample < -32768 )
incf PredSampleU,W
btfss STATUS,Z
goto DNewIndex
btfsc PredSampleH,7
goto DNewIndex
bcf STATUS,RP0 ; predsample = -32768;
clrf PredSampleL
movlw 0x80
movwf PredSampleH
; Find new quantizer step size by adding old index and a table lookup
; using the ADPCM code
DNewIndex
clrf PCLATH ;index += IndexTable[code];
bcf STATUS,RP0
movf Code,W
call IndexTable
bcf STATUS,RP0
addwf Index,F
; Check for overflow of the new quantizer step size index
btfsc Index,7 ;if( index < 0 )
clrf Index ; index = 0;
movlw 0x80 ;if( index > 88 )
xorwf Index,W
movwf 21
movlw 0x,D8
subwf 21,W
btfss STATUS,Z
btfss STATUS,C
goto DSave
movlw 0x58 ; index = 88;
bcf STATUS,RP0
movwf Index
; Save predicted sample & quantizer step size index for next iteration
DSave
bcf STATUS,RP0 ;state.prevsample = predsample;
movf PredSampleL,W
movwf PrevSampleL
clrf PrevSampleH
btfsc PrevSampleL,7
decf PrevSampleH
bcf STATUS,RP0 ;state.previndex = index;
movf Index,W
movwf PrevIndex
; Speech sample is in the registers PredSampleH:PredSampleL
return ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -