From Scott Dattalo
http://wwwsvr.eng.cam.ac.uk/comp.speech/Section2/Q2.7.html
http://wwws.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://wwwsvr.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) MILSTD188113,"Interoperability and Performance Standards ** for Analogto_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 Alaw.
...
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 ulaw encoded byte we wish to convert to it's ; linear form. ; ulaw2linear: mov W, <>ulawbyte and W, #$07 ; Get the exponent add PC, W jmp ulaw_exp0 jmp ulaw_exp1 jmp ulaw_exp2 jmp ulaw_exp3 jmp ulaw_exp4 jmp ulaw_exp5 jmp ulaw_exp6 ulaw_exp7 mov W, <<ulawbyte and W, #$1e mov ulaw_linhi, W add ulaw_linhi, W mov W, #LOW(127*132) mov ulaw_linlo, W mov W, #HIGH(127*132) add ulaw_linhi, W jmp ulaw_sign ulaw_exp6 mov W, <<ulawbyte and W, #$1e mov ulaw_linhi, W mov W, #LOW(63*132) mov ulaw_linlo, W mov W, #HIGH(63*132) add ulaw_linhi, W jmp ulaw_sign ulaw_exp5 mov W, ulawbyte and W, #$0f mov ulaw_linhi, W mov W, #LOW(31*132) mov ulaw_linlo, W mov W, #HIGH(31*132) add ulaw_linhi, W jmp ulaw_sign ulaw_exp4 mov W, >>ulawbyte and W, #$07 mov ulaw_linhi, W mov W, >>known_zero mov ulaw_linlo, W mov W, #LOW(15*132) add ulaw_linlo, W mov W, #HIGH(15*132) snb C inc ulaw_linhi add ulaw_linhi, W jmp ulaw_sign ulaw_exp3 mov W, >>ulawbyte and W, #$07 mov ulaw_linhi, W mov W, >>known_zero mov ulaw_linlo, W rr ulaw_linhi rr ulaw_linlo mov W, #LOW(7*132) add ulaw_linlo, W mov W, #HIGH(7*132) snb C inc ulaw_linhi add ulaw_linhi, W jmp ulaw_sign ulaw_exp2 mov W, <>ulawbyte and W, #$f0 mov ulaw_linlo, W add ulaw_linlo, W mov W, <<known_zero mov ulaw_linhi, W mov W, #LOW(3*132) add ulaw_linlo, W mov W, #HIGH(3*132) snb C inc ulaw_linhi add ulaw_linhi, W jmp ulaw_sign ulaw_exp0 mov W, <>ulawbyte mov ulaw_linlo, W mov W, >>ulaw_linlo and W, #$78 clr ulaw_linhi jmp ulaw_sign ulaw_exp1 mov W, <>ulawbyte and W, #$f0 mov ulaw_linlo, W clr ulaw_linhi mov W, #LOW(1*132) add ulaw_linlo, W mov W, #HIGH(1*132) snb C inc ulaw_linhi add ulaw_linhi, W ulaw_sign sb ulawbyte.7 ret not ulaw_linhi not ulaw_linlo inc ulaw_linhi incsz ulaw_linlo dec ulaw_linhi ret
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
mov W, <<ulawbyte ;w = xyzabcd? carry = s and W, #$1e ;w = 000abcd0 addlw 0x21 ;w = 001abcd1 carry=0 mov Hack, W mov W, #$21 ;w = 001abcd1 carry=0 add W, Hack mov ulaw_linlo, W clr ulaw_linhi snb ulawbyte.4 rl ulaw_linlo ;01abcd10 sb ulawbyte.5 jmp L1 ;If bit 4 and bit 5 are set then rl ulaw_linlo ; 1abcd100 rl ulaw_linlo ; abcd1000 rl ulaw_linhi ; 00000001 sb ulawbyte.6 jmp L2 swap ulaw_linhi swap ulaw_linlo ;shift left four positions mov W, ulaw_linlo and W, #$0f or ulaw_linhi, W ;;; xor ulaw_linlo, W ;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 mov W, #33 add ulaw_linlo, W sb C dec ulaw_linhi sb ulawbyte.7 jmp L4 not ulaw_linhi not ulaw_linlo inc ulaw_linhi incsz ulaw_linlo dec ulaw_linhi L4 rl lin_lo ;Final shift rl lin_hi ret
See also:
file: /Techref/scenix/lib/math/dsp/ulaw16bsd_sx.htm, 6KB, , updated: 2004/6/10 14:40, local time: 2022/5/20 03:42,

©2022 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.piclist.com/techref/scenix/lib/math/dsp/ulaw16bsd_sx.htm"> SX Microcontroller Math Method ulaw to 16bit linear</A> 
Did you find what you needed? 
PICList 2022 contributors:
o List host: MIT, Site host massmind.org, Top posters @20220520 * Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. ongoing support is MOST appreciated! * Contributors: Richard Seriani, Sr. 
Welcome to www.piclist.com! 
.