;			SOUND ZOOM
;
;		call from F-BASIC386 or High C
;	callm address,varptr(source),varptr(new),varptr(param),varptr(work)
;	void  SZOOM(*sourcesnd,*newsnd,*param,*work)
;
;
;			1990 3  Hiroshi TODA
;
;			1993 12 High C 用に改造
;
;	param: cycle , amp*10000H , time*10000H
;	work area = 256Byte
;
;

	.386p


param	struc

	dd	?
	dd	?
source	dd	?		; source snd.data address
new	dd	?		; new snd.data address
paradd	dd	?		; param. address
wadd	dd	? 		; work address

param   ends

work	struc

;data area

cycle	dd	?		; cycle
amp	dd	?		; amplitude expand rate
time	dd	?		; time expand rate
max	dd	?		; max length

;work area

rend	dd	?		; read end
rated	dd	?		; add rate
ratea	dd	?		; add buf.
lst1	dd	?		; loop start check
lst2	dd	?		; loop start
lend1	dd	?		; loop end check
lend2	dd	?		; loop end
pbuf	dd	?		; buf
	dd	?
	dd	?
count1	dd	?		; cycle count buf.
count2	dd	?		; cycle*10000H

work	ends


cseg	segment	dword public use32 'CODE'
	assume	cs:cseg,ds:cseg

	public	sndExpand
	db	'sndExpand',9
sndExpand	proc	near
	push	ebp
	mov	ebp,esp
	push	esi
	push	edi
	push	ebx

	mov	esi,[ebp].wadd		; esi <-- work area top add
	mov	ecx,[ebp].paradd	; ecx <-- para. add.
	xor	edx,edx			; edx=count
main01:	mov	eax,[ecx][edx*4]	; para. --> work area
	mov	[esi][edx*4],eax
	inc	edx
	cmp	edx,4
	jb	main01

	mov	ebx,[ebp].source	; ebx <-- source snd. add.
	mov	edi,[ebp].new		; edi <-- new snd. add.
	xor	edx,edx			; head trans
main02:	mov	eax,[ebx][edx*4]
	mov	[edi][edx*4],eax
	inc	edx
	cmp	edx,8
	jb	main02

	mov	eax,[esi].cycle		; count set
	cmp	eax,0
	jne	main00
	mov	eax,1
	mov	[esi].cycle,eax
main00:	mov	[esi].count1,eax
	xor	ecx,ecx			; ecx <-- counter
	mov	eax,[ebx+12]
	mov	[esi].rend,eax
	cmp	eax,0
	je	mainE
	mov	eax,[ebx+16]		; loop start
	add	eax,ebx
	add	eax,32
	mov	[esi].lst1,eax
	add	eax,[ebx+20]		; loop end
	mov	[esi].lend1,eax
	add	ebx,32			; add head(32Byte)
	add	edi,32
	add	[esi].rend,ebx
;	sub	[esi].rend,1					; 1993 12 -1は止める
	xor	eax,eax			; loop clear
	mov	[esi].lst2,eax
	mov	[esi].lend2,eax
	xor	eax,eax			; set time rate
	mov	[esi].ratea,eax
	cmp	dword ptr [esi].time,10000H
	jb	main03
	mov	eax,[esi].time		; hi
	sub	eax,10000H
	mov	[esi].rated,eax
	mov	eax,[esi].cycle		; set count2
	shl	eax,16
	mov	[esi].count2,eax
	jmp	main04
main03:	mov	eax,10000H
	sub	eax,[esi].time
	mov	[esi].rated,eax
	mov	eax,10000H		; set count2
	sub	eax,[esi].rated
	mul	dword ptr [esi].cycle
	mov	[esi].count2,eax

main04:	mov	al,[ebx]		; trans while zero
	mov	[edi],al
	cmp	ebx,[esi].lst1
	jne	main0A
	mov	[esi].lst2,ecx
main0A:	cmp	ebx,[esi].lend1
	jne	main0B
	mov	[esi].lend2,ecx
main0B:	inc	ecx
	inc	ebx
	inc	edi
	cmp	ebx,[esi].rend
	jae	mainE
	dec	dword ptr [esi].max
	je	mainE
	and	al,7fH
	je	main04
	dec	ebx
	dec	edi
	dec	ecx
	inc	dword ptr [esi].max
	cmp	dword ptr [esi].time,10000H
	jb	main05
	call	hi
	jmp	main06
main05:	call	lw
main06:	cmp	ecx,2000H		; data min length
	jae	main0D
	cmp	[esi].max,0
	je	main0D
	mov	al,80H
main0C:	mov	[edi],al
	dec	dword ptr [esi].max
	je	main0D
	inc	ecx
	inc	edi
	cmp	ecx,2000H
	jb	main0C
main0D:	mov	edi,[ebp].new		; edi <-- new snd. add.
	mov	[edi+12],ecx		; set length
	mov	eax,[esi].lst2		; set loop point
	cmp	eax,ecx
	jb	main07
	mov	eax,ecx
	dec	eax
main07:	mov	[edi+16],eax
	mov	eax,[esi].lend2		; set loop length
	sub	eax,[esi].lst2
	mov	edx,eax
	add	edx,[edi+16]
	cmp	edx,ecx
	jb	main08
	mov	eax,ecx
	sub	eax,[edi+16]
main08:	mov	[edi+20],eax

mainE:
	pop	ebx
	pop	edi
	pop	esi
	mov	esp,ebp
	pop	ebp
	ret

hi:	call	red			; read
	imul	dword ptr [esi].amp
	shrd	eax,edx,16
	call	wr			; write
	cmp	ebx,[esi].lst1		; sound loop check
	jne	hi0A
	mov	[esi].lst2,ecx
hi0A:	cmp	ebx,[esi].lend1
	jne	hi0B
	mov	[esi].lend2,ecx
hi0B:	inc	ecx
	dec	dword ptr [esi].max
	je	hiE

;	mov	ax,[edi-2]		; cross check
;	cmp	ax,8080H
;	je	hi00
;	and	eax,8080H
;	cmp	eax,80H

	call	close_ck

	jne	hi03
hi00:	mov	eax,[esi].rated		; ratea=ratea+rated
	add	[esi].ratea,eax
hi01:	mov	eax,[esi].ratea
	cmp	eax,[esi].count2
	jb	hi03
	sub	eax,[esi].count2
	mov	[esi].ratea,eax
	mov	[esi].pbuf,ebx		; make wave
	mov	eax,[esi].cycle		; set cycle count
	mov	[esi].count1,eax
hi02:	inc	ebx			; loop start
	call	red			; read
	imul	dword ptr [esi].amp
	shrd	eax,edx,16
	call	wr
	cmp	ebx,[esi].lst1		; sound loop check
	jne	hi0C
	mov	[esi].lst2,ecx
hi0C:	cmp	ebx,[esi].lend1
	jne	hi0D
	mov	[esi].lend2,ecx
hi0D:	inc	ecx
	cmp	ebx,[esi].rend
	jae	hiE
	dec	dword ptr [esi].max
	je	hiE

;	mov	ax,[edi-2]
;	cmp	ax,8080H
;	je	hi0E
;	and	eax,8080H
;	cmp	eax,80H

	call	close_ck

	jne	hi02			; loop end
hi0E:	dec	dword ptr [esi].count1	; cycle count
	jne	hi02
	mov	ebx,[esi].pbuf		; buf. -> ebx
	dec	edi			; 1Byte over write

;	dec		edi
;	mov		eax,[edi]
;	call	red2
;	sar		eax,2
;	call	wr

;	call	red
;	imul	dword ptr [esi].amp
;	shrd	eax,edx,16
;	sar		eax,2

	mov		eax,[edi-1]
	call	red2
	push	eax				; over write data を push

	inc		ebx				; 1つ先と平均化
	call	red			; read
	dec		ebx

	imul	dword ptr [esi].amp
	shrd	eax,edx,16

	add		[esp],eax
	pop		eax
	sar		eax,1			; over write data と 平均化

	call	wr
	jmp	hi01
hi03:	inc	ebx
	cmp	ebx,[esi].rend
	jb	hi
hiE:	ret

lw:	call	red			; read
	imul	dword ptr [esi].amp
	shrd	eax,edx,16
	call	wr			; write
	cmp	ebx,[esi].lst1		; sound loop check
	jne	lw0A
	mov	[esi].lst2,ecx
lw0A:	cmp	ebx,[esi].lend1
	jne	lw0B
	mov	[esi].lend2,ecx
lw0B:	inc	ecx
	dec	dword ptr [esi].max
	je	lwE

;	mov	ax,[edi-2]		; cross check
;	cmp	ax,8080H
;	je	lw00
;	and	eax,8080H
;	cmp	eax,80H

	call	close_ck

	jne	lw03
lw00:	mov	eax,[esi].rated		; ratea=ratea+rated
	add	[esi].ratea,eax
lw01:	mov	eax,[esi].ratea
	cmp	eax,[esi].count2
	jb	lw03
	sub	eax,[esi].count2	; delete wave
	mov	[esi].ratea,eax
	mov	[esi].pbuf,ecx		; count(ecx,edi,max) -> buf.
	mov	[esi].pbuf+4,edi
	mov	eax,[esi].max
	mov	[esi].pbuf+8,eax
	mov	eax,[esi].cycle		; set cycle count
	mov	[esi].count1,eax
lw02:	inc	ebx			; loop start
	call	red			; read
	imul	dword ptr [esi].amp
	shrd	eax,edx,16
	call	wr
	cmp	ebx,[esi].lst1		; sound loop check
	jne	lw0C
	mov	[esi].lst2,ecx
lw0C:	cmp	ebx,[esi].lend1
	jne	lw0D
	mov	[esi].lend2,ecx
lw0D:	inc	ecx
	cmp	ebx,[esi].rend
	jae	lwE
	dec	dword ptr [esi].max
	je	lwE

;	mov	ax,[edi-2]
;	cmp	ax,8080H
;	je	lw0E
;	and	eax,8080H
;	cmp	eax,80H

	call	close_ck

	jne	lw02			; loop end
lw0E:	dec	dword ptr [esi].count1	; cycle count
	jne	lw02
	mov	ecx,[esi].pbuf		; buf. -> count(ecx,edi)
	mov	edi,[esi].pbuf+4
	mov	eax,[esi].pbuf+8
	mov	[esi].max,eax
	dec	edi			; 1Byte over write

;	dec		edi
;	mov		eax,[edi]
;	call	red2
;	sar		eax,2
;	call	wr

;	call	red
;	imul	dword ptr [esi].amp
;	shrd	eax,edx,16
;	sar		eax,2

	mov		eax,[edi-1]
	call	red2
	push	eax				; over write data を push

	inc		ebx				; 1つ先と平均化
	call	red			; read
	dec		ebx

	imul	dword ptr [esi].amp
	shrd	eax,edx,16

	add		[esp],eax
	pop		eax
	sar		eax,1			; over write data と 平均化

	call	wr
	jmp	lw01
lw03:	inc	ebx
	cmp	ebx,[esi].rend
	jb	lw
lwE:	ret



;	edi-4を境にクロスしてるかをフィルタ(平均化)にかけて判断
;	eax = 0ならクロス, eax != 0ならノンクロス

close_ck:
	push	ecx
	push	edx

;	mov		eax,[edi-8]
	mov		eax,[ebx-2]		; オリジナルを見るように変更

	shld	edx,eax,8
	cmp		dl,80h
	jb		cls00
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls00:
	movsx	edx,dl
	mov		ecx,edx

	shld	edx,eax,16
	cmp		dl,80h
	jb		cls01
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls01:
	movsx	edx,dl
	add		ecx,edx
	add		ecx,edx

	shld	edx,eax,24
	cmp		dl,80h
	jb		cls02
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls02:
	movsx	edx,dl
	add		ecx,edx

	shld	edx,eax,32
	cmp		dl,80h
	jb		cls03
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls03:
	movsx	edx,dl
;	add		ecx,edx

	cmp		ecx,0
;	jge		cls_no
	jg		cls_no

;	mov		eax,[edi-4]
	mov		eax,[ebx-1]		; オリジナルを見るように変更

	shld	edx,eax,8
	cmp		dl,80h
	jb		cls10
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls10:
	movsx	edx,dl
	mov		ecx,edx

	shld	edx,eax,16
	cmp		dl,80h
	jb		cls11
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls11:
	movsx	edx,dl
	add		ecx,edx
	add		ecx,edx

	shld	edx,eax,24
	cmp		dl,80h
	jb		cls12
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls12:
	movsx	edx,dl
	add		ecx,edx

	shld	edx,eax,32
	cmp		dl,80h
	jb		cls13
	mov		dh,dl
	mov		dl,80h
	sub		dl,dh
cls13:
	movsx	edx,dl
;	add		ecx,edx

	cmp		ecx,0
;	jle		cls_no
	jl		cls_no

	xor		eax,eax
	jmp		cls_end

cls_no:
	xor		eax,eax
	sub		eax,1

cls_end:
	pop		edx
	pop		ecx
	ret


;	WRITE DATA
;	eax -> pcm data -> [edi] & inc edi

wr:	cmp	eax,0			; write
	js	wr01
	je	wr01
	cmp	eax,128			; +
	jb	wr02
	mov	eax,127
	jmp	wr02
wr01:	mov	edx,eax			; -
	mov	eax,128
	sub	eax,edx
	cmp	eax,256-1	; data255はloopStopの意味があるから除外 1993 12
	jb	wr02
	mov	eax,255-1	; data255はloopStopの意味があるから除外 1993 12
wr02:	mov	[edi],al
	inc	edi
	ret

;	PCM DATA READ
;	[ebx] -> output eax

red:	mov	al,[ebx]		; read
red2:	and	eax,0ffH	; eaxにあるpcm dataをsigned intに変換するときに呼ぶ
	cmp	eax,128
	jb	red01
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
red01:	ret

sndExpand	endp

cseg	ends

	end
