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: 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

file: /Techref/scenix/lib/math/dsp/ulaw-16b-sd_sx.htm, 6KB, , updated: 2004/6/10 14:40, local time: 2023/3/23 10:14, |

©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://www.sxlist.com/Techref/scenix/lib/math/dsp/ulaw-16b-sd_sx.htm"> SX Microcontroller Math Method ulaw to 16bit linear</A> |

Did you find what you needed? |

## Welcome to sxlist.com!sales, advertizing, & kind contributors
just like you! Please don't rip/copy
(here's why Copies of the site on CD are available at minimal cost. |

## Welcome to www.sxlist.com! |

.