please dont rip this site

SX Microcontroller DSP Math Method

ulaw to 16bit linear

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 13:40, local time: 2024/11/20 03:30,
TOP NEW HELP FIND: 
3.137.172.53:LOG IN

 ©2024 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://linistepper.com/Techref/scenix/lib/math/dsp/ulaw-16b-sd_sx.htm"> SX Microcontroller 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?