;$Author:   DCODY  $
;$Date:   23 Jun 1992 16:32:18  $
;$Header:   W:/sccs/misc/histo.asv   1.1   23 Jun 1992 16:32:18   DCODY  $
;$Log:   W:/sccs/misc/histo.asv  $
;  
;     Rev 1.1   23 Jun 1992 16:32:18   DCODY
;  PAS2 update
;  
;     Rev 1.0   15 Jun 1992 09:39:52   BCRANE
;  Initial revision.
;$Logfile:   W:/sccs/misc/histo.asv  $
;$Modtimes$
;$Revision:   1.1  $

	Title Media Vision Histogram routines
	page	64,131

;   /*\
;---|*|----====< HISTO.ASM >====----
;---|*|
;---|*| These routines create a histogram from the block of PCM samples
;---|*|
;---|*| MakeHistoGram	  (char far *, int-1, int-2)
;---|*| MakeHalfHistoGram (char far *, int-1, int-2)
;---|*|
;---|*|   char far * (wParm1) is the buffer pointer
;---|*|   int-1      (wParm2) is the buffer length in bytes
;---|*|   int-2      (wParm3) is the offset from the center line to accumulate
;---|*|
;---|*| The Return value is the count of samples over the offset
;---|*|
;   \*/

	.xlist
	include model.inc
        include masm.inc
;;;;;;;;include target.inc
        .list

        .data

	public	HistoGram256
HistoGram256	dw	256 dup(0)	; 256 word table for histogram accum

	extrn	__pcmdatasize:byte	; data size - 8 or 16 bit PCM

	.code

;   /*\
;---|*|------------------=============================------------------
;---|*|------------------====< MakeHalfHistoGram >====------------------
;---|*|------------------=============================------------------
;   \*/
;
;   This routine folds the high order samples into the low order, via
;   ones compliment. Since it uses ones compliment, the folded values
;   will shift down one value (an effective increase in aplituded by
;   a factor of 1/256). The benefit is a faster accumulation. This
;   routine is used to find how many samples pass the threshold of noise.
;   This "noise" is wParm3, the offset from the center line.
;
        public MakeHalfHistoGram
MakeHalfHistoGram proc
	push	bp
	mov	bp,sp
;
; save the critcals
;
	push	es
	push	di
	push	si
;
; flush the table
;
	push	ds			; clear the block
	pop	es
	lea	di,HistoGram256
	sub	ax,ax
	mov	cx,100h
	cld
	rep	stosw
	lea	di,HistoGram256 	; es:di point to the table
;
; get the two parameters
;
    if @datasize
	les	si,wParm1		; get the target buffer pointer
	mov	cx,wParm3		; get the buffer length
    else
	mov	si,wParm1		; get the target buffer pointer
	mov	cx,wParm2		; get the buffer length
    endif
;
; handle the 16 bit data as 8 bit
;
	sub	dx,dx			; dx has an XOR mask to convert 16 to 8
	cmp	__pcmdatasize,8 	; 8 bit data?
	jz	@F			; yes, continue on...
        mov     dx,0180h                ; to flip the data byte to 8 bits
	shr	cx,1			; cut the buffer in half
	inc	si			; point to the most significant byte
    ;
    @@:
;
; make the histogram
;
mhhg05:
    if @datasize
	lods	byte ptr es:[si]	; get the next byte of data
    else
	lodsb
    endif

	neg	dh			; set the carry if 16 bit data
	adc	si,0			; adjust si to the next high byte
	xor	al,dl			; if 16 bit data, convert to 8 bit

	cbw				; if al > 7f, do a 1s compliment
	xor	al,ah
	cbw				; clear ah

        mov     bx,ax
	add	bx,ax
	inc	wptr [di+bx]		; increment the word

        loop    mhhg05
	mov	bx,cx			; clear bx
;
; count all the entries starting at the offset
;
	mov	cl,80h
    if @datasize
	sub	cl,bptr wParm4		; cx holds the count
    else
        sub     cl,bptr wParm3          ; cx holds the count
    endif
	lea	si,HistoGram256 	; si points to the start of the table
;
mhhg20:
	lodsw
	add	bx,ax
	loop	mhhg20

	mov	ax,bx			; return the count
;
; all done, exit home...
;
	pop	si
	pop	di
	pop	es
	pop	bp
	ret

MakeHalfHistoGram endp

;   /*\
;---|*|---------------------=========================---------------------
;---|*|---------------------====< MakeHistoGram >====---------------------
;---|*|---------------------=========================---------------------
;   \*/
;
;   This routine builds a full histogram of the caller's buffer.
;
        public   MakeHistoGram
MakeHistoGram	proc
	push	bp
	mov	bp,sp
;
; save the critcals
;
	push	es
	push	di
	push	si
;
; flush the table
;
        push    ds                      ; clear the block
	pop	es
	lea	di,HistoGram256
	sub	ax,ax
	mov	cx,100h
	cld
	rep	stosw
	lea	di,HistoGram256 	; es:di point to the table
;
; get the two parameters
;
    if @datasize
	les	si,wParm1		; get the target buffer pointer
	mov	cx,wParm3		; get the buffer length
    else
	mov	si,wParm1		; get the target buffer pointer
	mov	cx,wParm2		; get the buffer length
    endif
;
; handle the 16 bit data as 8 bit
;
        sub     dx,dx                   ; dx has an XOR mask to convert 16 to 8
	cmp	__pcmdatasize,8 	; 8 bit data?
	jz	@F			; yes, continue on...
        mov     dx,0180h                ; to flip the data byte to 8 bits
	shr	cx,1			; cut the buffer in half
	inc	si			; point to the most significant byte
    ;
    @@:
;
; make the histogram
;
mhg05:
    if @datasize
	lods	byte ptr es:[si]
    else
	lodsb
    endif

	neg	dh			; set the carry if 16 bit data
	adc	si,0			; adjust si to the next high byte
	xor	al,dl			; if 16 bit data, convert to 8 bit

        mov     bx,ax
	shl	bx,1
	inc	wptr [di+bx]
        loop    mhg05
;
; count all high entries based upon the offset
;
    if @datasize
	sub	cl,bptr wParm4		; cx holds the count
    else
        sub     cl,bptr wParm3          ; cx holds the count
    endif
	lea	si,HistoGram256 	; si points to the start of the table
	add	si,100h 		; move to the centerline
	add	si,cx			; adjust to the starting index
	add	si,cx
	sub	cx,80h			; cx will hold an index from 80h to ffh
	neg	cx
	and	cx,07fh 		; make sure its valid
	sub	bx,bx			; bx holds the accumulated value
;
mhg10:
	lodsw
	add	bx,ax
	loop	mhg10
;
; count all the low entries based upon the offset
;
	mov	cl,80h
    if @datasize
	sub	cl,bptr wParm4		; cx holds the count
    else
        sub     cl,bptr wParm3          ; cx holds the count
    endif
        lea     si,HistoGram256         ; si points to the start of the table
;
mhg20:
	lodsw
	add	bx,ax
	loop	mhg20

	mov	ax,bx			; return the count
;
; all done, exit home...
;
	pop	si
	pop	di
	pop	es
	pop	bp
	ret

MakeHistoGram	endp
;
        end
;
