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 15:32, local time: 2025/10/25 08:41,
216.73.216.180,10-8-63-169:LOG IN
|
| ©2025 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://www.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! |
|
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.