Searching \ for 'A-law or mu-law to linear conversion.' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: piclist.com/techref/index.htm?key=law+law+linear+conversion
Search entire site for: 'A-law or mu-law to linear conversion.'.

Truncated match.
PICList Thread
'A-law or mu-law to linear conversion.'
2000\03\31@004152 by Terry

flavicon
face
Anyone know of a method to convert 8 bit A or mu-law to 16 bit linear fast
and compact using a 16c72?
Is a lookup table the only way?

Cheers
Terry


'A-law or mu-law to linear conversion.'
2000\04\01@170201 by Scott Dattalo
face
flavicon
face
On Fri, 31 Mar 2000, Terry wrote:

> Anyone know of a method to convert 8 bit A or mu-law to 16 bit linear fast
> and compact using a 16c72?
> Is a lookup table the only way?

I don't know the specifics on mu-law other than it involves logarithmic
compression. A quick search on the web led me to:

http://www-s.ti.com/sc/psheets/spra267/spra267.pdf

>From which I copied this table:

          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

Is this correct?

If so, here's an untested solution off the top-of-my-head:

   clrf  lin_hi
   movf  mu_law,w
   andlw 0x0f
   iorlw 0x10
   movwf lin_lo

   btfsc mu_law,4    ;shift left once
    rlf  lin_lo,f

   btfss mu_law,5    ;shift left two positions
    goto L1

   rlf   lin_lo,f
   rlf   lin_lo,f

L1:
   btfss mu_law,6
    goto L2

   swapf lin_lo,f    ;shift left four positions
   movf  lin_lo,w
   andlw 0x0f
   movwf lin_hi
;;; xorwf lin_lo,f    ;probably unnecessary to clear lsbs
                     ;since they are "don't cares"...

L2:
   rlf   lin_lo,f    ;Final shift
   rlf   lin_hi,f


Is this fast and compact enough?


Scott

2000\04\02@143746 by Terry

flavicon
face
At 04:00 PM 4/1/00 -0600, you wrote:
>On Fri, 31 Mar 2000, Terry wrote:
>
>> Anyone know of a method to convert 8 bit A or mu-law to 16 bit linear fast
>> and compact using a 16c72?
>> Is a lookup table the only way?
>
>I don't know the specifics on mu-law other than it involves logarithmic
>compression. A quick search on the web led me to:

Scott i could kiss you. Not tested the code yet but it looks good. Many
thanks for pointing the way. I'd buy you a seafood feast if we weren't so
far apart.

Cheers
Terry

2000\04\02@175716 by Plunkett, Dennis

flavicon
face
{Quote hidden}

       I don't think so 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.


       Dennis




{Quote hidden}

2000\04\02@201624 by Terry

flavicon
face
At 07:55 AM 4/3/00 +1000, you wrote:
{Quote hidden}

Dennis

It's mu-law there without the sign bit and median approximation, other then
that Scott's written a super conversion code.

Cheers
Terry

2000\04\03@080938 by Scott Dattalo

face
flavicon
face
On Mon, 3 Apr 2000, Plunkett, Dennis wrote:

{Quote hidden}

It's always easier to say what isn't than what is. 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.

Now, the pic code I posted yesterday only implements a very small portion. But
that's easy to fix.

A couple of observations first:

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

There, that should be better.

Scott

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...