;			FREQENCY CHANGER
;
;		call from F-BASIC386 or High C
;	callm address,varptr(source),varptr(new),varptr(param),varptr(work)
;	void  FCHAN(*sourcesnd,*newsnd,*param,*work)
;
;
;			1990 3  Hiroshi TODA
;
;			1993 12 High C 用に改造
;
;	param: FreqencyExpandRate(mode)*10000H , MaxDataLength
;	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

mode	dd	?		; rate
max	dd	?		; max length

;work area

point	dd	?		; ov.sampling point (decimal)
	dd	?		; ov.sampling point (integer)
rate	dd	?		; add (decimal)
	dd	?		; add (integer)
rend	dd	?		; read end

work	ends


cseg	segment	dword public use32 'CODE'
	assume	cs:cseg,ds:cseg

	public	sndPitch
	db	'sndPitch',8
sndPitch	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,2
	jb	main01
	mov	eax,[esi].mode
	cmp	eax,10H
	ja	main0A
	mov	eax,10H
	mov	[esi].mode,eax	; 1994 1 この行を追加,これがないとmode=0のとき多分暴走

main0A:	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

	xor	ecx,ecx			; ecx <-- counter
	mov	eax,[ebx+12]
	mov	[esi].rend,eax
	cmp	eax,0
	je	mainE
	add	ebx,32			; add head(32Byte)
	add	edi,32
	add	[esi].rend,ebx
	sub	[esi].rend,1 		; endDataに等しいaddrを感知する必要があるため
	mov	[esi].point+4,ebx	; set integer
	xor	edx,edx
	mov	[esi].point,edx		; decimal = 0
	mov	eax,[esi].mode
	shld	edx,eax,16
	shl	eax,16
	mov	[esi].rate,eax
	mov	[esi].rate+4,edx
	call	lp
	cmp	ecx,2000H		; data min length >=2000H
	jae	main0C
	cmp	[esi].max,0
	je	main0C
	mov	al,80H			; make 0 data
main0B:	mov	[edi],al
	dec	dword ptr [esi].max
	je	main0C
	inc	ecx
	inc	edi
	cmp	ecx,2000H
	jb	main0B
main0C:	mov	edi,[ebp].new		; edi <-- new snd. add.
	mov	[edi+12],ecx		; set length
	xor	eax,eax			; set loop point
	mov	edx,01H
	div	dword ptr [esi].mode
	mul	dword ptr [edi+16]
	shrd	eax,edx,16
	cmp	eax,ecx
	jb	main03
	mov	eax,ecx
	dec	eax
main03:	mov	[edi+16],eax
	xor	eax,eax			; set loop length
	mov	edx,01H
	div	dword ptr [esi].mode
	mul	dword ptr [edi+20]
	shrd	eax,edx,16
	mov	edx,eax
	add	edx,[edi+16]
	cmp	edx,ecx
	jb	main04
	mov	eax,ecx
	sub	eax,[edi+16]
main04:	mov	[edi+20],eax
mainE:
	pop	ebx
	pop	edi
	pop	esi
	mov	esp,ebp
	pop	ebp
	ret

lp:	lea	eax,[esi].point
	call	smp			; ov.smp.

	mov	edx,[esi].point+4	; 終了チェック
	cmp	edx,[esi].rend
	jb	lp01

	mov	eax,[esi].rend	; データの終わりの例外処理
	mov	al,[eax]
	and	eax,0ffH
	cmp	eax,128
	jb	lp01
	mov	edx,eax
	mov	eax,128
	sub	eax,edx

lp01:
	call	wr			; write
	inc	ecx
	dec	dword ptr [esi].max
	je	lpE
	call	adp

	mov	edx,[esi].point+4	; 終了チェック
	cmp	edx,[esi].rend
	jbe	lp

lpE:	ret

;	POINT=POINT+RATE

adp:	push	eax
	push	edx
	mov	eax,[esi].point
	mov	edx,[esi].point+4
	add	eax,[esi].rate
	adc	edx,[esi].rate+4
	mov	[esi].point,eax
	mov	[esi].point+4,edx
	pop	edx
	pop	eax
	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

;	OVER SAMPLING for PCM DATA(8bit)
;input	eax = 64bit(32bit/decimal,32bit/integer) data address(ds:)
;output	eax = over sampring data ( 32bit sign (-128 -- +127) )

smp:	push	ebx
	push	ecx
	push	edx
	push	esi
	push	edi
	mov	ebx,[eax]		; ebx = decimal
	mov	esi,[eax+4]		; esi = integer
	shr	ebx,24			; ebx --> 8bit
	jne	smp00

	mov	al,[esi]		; decimal=0
	and	eax,0ffH
	cmp	eax,128
	jb	smp0A
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
smp0A:	jmp	smp06

smp00:
	mov	eax,[esi-1]		; 周囲がみな無信号ならノイズを出さないよう直接0を返す
	cmp	eax,80808080h
	jne	smp0B
	xor	eax,eax
	jmp	smp06

smp0B:
	call	smp01
smp01:	pop	edi
	add	edi,smptb-smp01		; edi = table point

	mov	al,[esi]
	and	eax,0ffH
	cmp	eax,128
	jb	smp02
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
smp02:	add	eax,128
	mul	byte ptr cs:[edi][ebx]
	mov	ecx,eax

	mov	al,[esi-1]
	and	eax,0ffH
	cmp	eax,128
	jb	smp03
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
smp03:	add	eax,128
	mul	byte ptr cs:[edi][ebx+256]
	sub	ecx,eax

	mov	eax,ebx			; ebx = 256 - ebx
	mov	ebx,256
	sub	ebx,eax

	mov	al,[esi+1]
	and	eax,0ffH
	cmp	eax,128
	jb	smp04
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
smp04:	add	eax,128
	mul	byte ptr cs:[edi][ebx]
	add	ecx,eax

	mov	al,[esi+2]
	and	eax,0ffH
	cmp	eax,128
	jb	smp05
	mov	edx,eax
	mov	eax,128
	sub	eax,edx
smp05:	add	eax,128
	mul	byte ptr cs:[edi][ebx+256]
	sub	ecx,eax
	sub	ecx,128*256
	sar	ecx,8
	mov	eax,ecx

smp06:	pop	edi
	pop	esi
	pop	edx
	pop	ecx
	pop	ebx
	ret	

smptb	db	255,255,255,254,254,253,253,252
	db	252,251,251,250,249,249,248,248
	db	247,246,246,245,244,244,243,243
	db	242,241,240,240,239,238,238,237
	db	236,236,235,234,233,233,232,231
	db	230,229,229,228,227,226,225,225
	db	224,223,222,221,221,220,219,218
	db	217,216,215,214,214,213,212,211
	db	210,209,208,207,206,205,204,204
	db	203,202,201,200,199,198,197,196
	db	195,194,193,192,191,190,189,188
	db	187,186,185,184,183,182,181,180
	db	179,178,177,176,175,174,172,171
	db	170,169,168,167,166,165,164,163
	db	162,161,160,158,157,156,155,154
	db	153,152,151,150,148,147,146,145
	db	144,143,142,141,139,138,137,136
	db	135,134,133,132,130,129,128,127
	db	126,125,123,122,121,120,119,118
	db	117,115,114,113,112,111,110,108
	db	107,106,105,104,103,101,100,099
	db	098,097,096,094,093,092,091,090
	db	089,087,086,085,084,083,082,080
	db	079,078,077,076,075,073,072,071
	db	070,069,068,067,065,064,063,062
	db	061,060,058,057,056,055,054,053
	db	052,051,049,048,047,046,045,044
	db	043,042,040,039,038,037,036,035
	db	034,033,032,030,029,028,027,026
	db	025,024,023,022,021,020,019,018
	db	016,015,014,013,012,011,010,009
	db	008,007,006,005,004,003,002,001

	db	000,000,001,001,001,002,002,002
	db	003,003,003,003,004,004,004,005
	db	005,005,005,006,006,006,006,007
	db	007,007,007,008,008,008,008,009
	db	009,009,009,009,010,010,010,010
	db	010,011,011,011,011,011,011,012
	db	012,012,012,012,012,013,013,013
	db	013,013,013,013,014,014,014,014
	db	014,014,014,014,014,015,015,015
	db	015,015,015,015,015,015,015,015
	db	015,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,016,016,016,016,016,016
	db	016,016,015,015,015,015,015,015
	db	015,015,015,015,015,015,015,015
	db	014,014,014,014,014,014,014,014
	db	014,014,014,013,013,013,013,013
	db	013,013,013,013,012,012,012,012
	db	012,012,012,012,012,011,011,011
	db	011,011,011,011,011,010,010,010
	db	010,010,010,010,009,009,009,009
	db	009,009,009,008,008,008,008,008
	db	008,008,007,007,007,007,007,007
	db	007,006,006,006,006,006,006,005
	db	005,005,005,005,005,004,004,004
	db	004,004,004,003,003,003,003,003
	db	003,002,002,002,002,002,002,001
	db	001,001,001,001,001,000,000,000

sndPitch	endp

cseg	ends
	end
