please dont rip this site

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: 2022/12/5 16:57,
TOP NEW HELP FIND: 
3.239.112.140:LOG IN

 ©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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://www.massmind.org/techref/microchip/dsp/ulaw-16b-sd.htm"> PIC Microcontoller Math Method ulaw to 16bit linear</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

 

Welcome to massmind.org!

 

Welcome to www.massmind.org!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .