From Scott Dattalo
http://www-svr.eng.cam.ac.uk/comp.speech/Section2/Q2.7.html
http://www-s.ti.com/sc/psheets/spra267/spra267.pdf
shows:
> > linear compressed > > 12 11 10 9 8 7 6 5 4 3 2 1 0 | 6 5 4 3 2 1 0 > > ---------------------------------------------------------- > > 0 0 0 0 0 0 0 1 Q3 Q2 Q1 Q0 x 0 0 0 Q3 Q2 Q1 Q0 > > 0 0 0 0 0 0 1 Q3 Q2 Q1 Q0 x x 0 0 1 Q3 Q2 Q1 Q0 > > 0 0 0 0 0 1 Q3 Q2 Q1 Q0 x x x 0 1 0 Q3 Q2 Q1 Q0 > > 0 0 0 0 1 Q3 Q2 Q1 Q0 x x x x 0 1 1 Q3 Q2 Q1 Q0 > > 0 0 0 1 Q3 Q2 Q1 Q0 x x x x x 1 0 0 Q3 Q2 Q1 Q0 > > 0 0 1 Q3 Q2 Q1 Q0 x x x x x x 1 0 1 Q3 Q2 Q1 Q0 > > 0 1 Q3 Q2 Q1 Q0 x x x x x x x 1 1 0 Q3 Q2 Q1 Q0 > > 1 Q3 Q2 Q1 Q0 x x x x x x x x 1 1 1 Q3 Q2 Q1 Q0
Now, A law has alternate bit inversion, and this only seems to have 7 bits compressed. Just remember that in the compressed for each bit is equal to 3dB up to 0dBmO.
Another search yielded a C solution:
http://www-svr.eng.cam.ac.uk/comp.speech/Section2/Q2.7.html
The portion of interest:
/* ** This routine converts from ulaw to 16 bit linear. ** ** Craig Reese: IDA/Supercomputing Research Center ** 29 September 1989 ** ** References: ** 1) CCITT Recommendation G.711 (very difficult to follow) ** 2) MIL-STD-188-113,"Interoperability and Performance Standards ** for Analog-to_Digital Conversion Techniques," ** 17 February 1987 ** ** Input: 8 bit ulaw sample ** Output: signed 16 bit linear sample */ int ulaw2linear(ulawbyte) unsigned char ulawbyte; { static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; int sign, exponent, mantissa, sample; ulawbyte = ~ulawbyte; sign = (ulawbyte & 0x80); exponent = (ulawbyte >> 4) & 0x07; mantissa = ulawbyte & 0x0F; sample = exp_lut[exponent] + (mantissa << (exponent + 3)); if (sign != 0) sample = -sample; return(sample); }
This is ulaw and not A-law.
...
The array exp_lut[8] can be expressed:
exp_lut[i] = 132 *( (2^i) - 1)
You could use a look up table (like in the C code) or you could calculate it. But since there are only 8 cases, I think a table approach is fastest
; ulawbyte contains the u-law encoded byte we wish to convert to it's ; linear form. ; ulaw2linear: swapf ulawbyte,w andlw 0x07 ; Get the exponent addwf pcl,f goto ulaw_exp0 goto ulaw_exp1 goto ulaw_exp2 goto ulaw_exp3 goto ulaw_exp4 goto ulaw_exp5 goto ulaw_exp6 ulaw_exp7 rlf ulawbyte,w andlw 0x1e movwf ulaw_linhi addwf ulaw_linhi,f movlw LOW(127*132) movwf ulaw_linlo movlw HIGH(127*132) addwf ulaw_linhi,f goto ulaw_sign ulaw_exp6 rlf ulawbyte,w andlw 0x1e movwf ulaw_linhi movlw LOW(63*132) movwf ulaw_linlo movlw HIGH(63*132) addwf ulaw_linhi,f goto ulaw_sign ulaw_exp5 movf ulawbyte,w andlw 0x0f movwf ulaw_linhi movlw LOW(31*132) movwf ulaw_linlo movlw HIGH(31*132) addwf ulaw_linhi,f goto ulaw_sign ulaw_exp4 rrf ulawbyte,w andlw 0x07 movwf ulaw_linhi rrf known_zero,w movwf ulaw_linlo movlw LOW(15*132) addwf ulaw_linlo movlw HIGH(15*132) skpnc incf ulaw_linhi,f addwf ulaw_linhi,f goto ulaw_sign ulaw_exp3 rrf ulawbyte,w andlw 0x07 movwf ulaw_linhi rrf known_zero,w movwf ulaw_linlo rrf ulaw_linhi,f rrf ulaw_linlo,f movlw LOW(7*132) addwf ulaw_linlo,f movlw HIGH(7*132) skpnc incf ulaw_linhi,f addwf ulaw_linhi,f goto ulaw_sign ulaw_exp2 swapf ulawbyte,w andlw 0xf0 movwf ulaw_linlo addwf ulaw_linlo,f rlf known_zero,w movwf ulaw_linhi movlw LOW(3*132) addwf ulaw_linlo,f movlw HIGH(3*132) skpnc incf ulaw_linhi,f addwf ulaw_linhi,f goto ulaw_sign ulaw_exp0 swapf ulawbyte,w movwf ulaw_linlo rrf ulaw_linlo,w andlw 0x78 clrf ulaw_linhi goto ulaw_sign ulaw_exp1 swapf ulawbyte,w andlw 0xf0 movwf ulaw_linlo clrf ulaw_linhi movlw LOW(1*132) addwf ulaw_linlo,f movlw HIGH(1*132) skpnc incf ulaw_linhi,f addwf ulaw_linhi,f ulaw_sign btfss ulawbyte,7 return comf ulaw_linhi,f comf ulaw_linlo,f incf ulaw_linhi,f incfsz ulaw_linlo,f decf ulaw_linhi,f return
Now, this is untested and unoptimized, but it's close to being right and as fast as possible. If you want a shorter routine that's somewhat slower, then a slight modification of my last post will work. It takes advantage of the fact that:
132 = 4 * 33
and
(2^n - 1) * X = (X << n) - X
If ulawbyte is formatted:
sxyzabcd s - sign xyz - exponent abcd - mantissa
Then this routine will convert it to the linear form
rlf ulawbyte,w ;w = xyzabcd? carry = s andlw 0x1e ;w = 000abcd0 addlw 0x21 ;w = 001abcd1 carry=0 movwf ulaw_linlo clrf ulaw_linhi btfsc ulawbyte,4 rlf ulaw_linlo,f ;01abcd10 btfss ulawbyte,5 goto L1 ;If bit 4 and bit 5 are set then rlf ulaw_linlo,f ; 1abcd100 rlf ulaw_linlo,f ; abcd1000 rlf ulaw_linhi,f ; 00000001 btfss ulawbyte,6 goto L2 swapf ulaw_linhi,f swapf ulaw_linlo,f ;shift left four positions movf ulaw_linlo,w andlw 0x0f iorwf ulaw_linhi ;;; xorwf ulaw_linlo,f ;probably unnecessary to clear lsbs ;since they are "don't cares"... L2: ;; If the sign bit is set, then we need to compute ;; 33 - ulaw_linhi:ulaw_linhi ;; otherwise we need ;; ulaw_linhi:ulaw_linhi - 33 movlw -33 addwf ulaw_linlo,f skpc decf ulaw_linhi,f btfss ulawbyte,7 goto L4 comf ulaw_linhi,f comf ulaw_linlo,f incf ulaw_linhi,f incfsz ulaw_linlo,f decf ulaw_linhi,f L4 rlf lin_lo,f ;Final shift rlf lin_hi,f return
Questions:
file: /Techref/microchip/dsp/ulaw-16b-sd.htm, 6KB, , updated: 2005/5/6 14:32, local time: 2023/12/4 01:50, |
©2023 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/Techref/microchip/dsp/ulaw-16b-sd.htm"> PIC Microcontoller Math Method ulaw to 16bit linear</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to techref.massmind.org! |
.