*****************************************************************
*								*
*	maestix.library-Demo:	Surround			*
*								*
*****************************************************************
*
*	Programmed by		Richard Körber
*	Date			1995-02-01
*
*****************************************************************
*  This demonstration shows how  to realise a real time effect  *
*  using the maestix library.  It allocates the Maestro sound-	*
*  card,  select the default input and sends the surround sig-	*
*  nal to output.						*
*****************************************************************

		INCDIR	"include:"
		INCLUDE	exec.i			; Library call macros
		INCLUDE	intuition.i
		INCLUDE	graphics.i
		INCLUDE	dos.i
		INCLUDE	maestix.i
		INCLUDE	libraries/maestix.i	;Reference includes
		INCLUDE	intuition/intuition.i
		INCLUDE	dos/dostags.i
		INCLUDE	exec/ports.i

BUFSIZE		EQU	24*1024			;size of FIFO data block

		SECTION text,CODE

*---------------------------------------------------------------*
*	== START OF PROGRAM ==					*
*								*
start	;-- Open all libraries -----------------;
		lea	maestname(PC),a1	;maestix
		moveq	#35,d0			; V35+
		exec	OpenLibrary		; open
		move.l	d0,maestbase		; store base
		beq	error1			; not found!
		lea	intuiname(PC),a1	;intuition
		moveq	#36,d0			; V36+
		exec	OpenLibrary		; open
		move.l	d0,intuibase		; store base
		beq	error2			; not found!
		lea	dosname(PC),a1		;dos
		moveq	#36,d0			; V36+
		exec	OpenLibrary		; open
		move.l	d0,dosbase		; store base
		beq	error3
	;-- Create buffer ----------------------;
		move.l	#BUFSIZE*5,d0		;size of five buffers
		move.l	#$10001,d1		;PUBLIC|CLEAR
		exec	AllocMem
		move.l	d0,buffer
		beq	error4
	;-- Alloc signal bits ------------------;
		sub.l	a1,a1			;get task ptr
		exec	FindTask
		move.l	d0,maintask
		moveq	#-1,d0			;Allocate a 2nd signal bit
		exec	AllocSignal
		move.b	d0,donesigbit
		cmp.b	#-1,d0			;no signals free?
		beq.w	error5
	;-- Open handle window -----------------;
		sub.l	a0,a0			;no newwindow struct
		lea	windowtags(PC),a1	; but loads of tags
		intui	OpenWindowTagList
		move.l	d0,window
		beq	error6
	;-- Launch surround task ---------------;
		move.l	#tasktags,d1		;Tags for new task
		dos	CreateNewProc		;create new process
		tst.l	d0			;got the task?
		beq	error7
		moveq	#0,d0			;wait 'till 2nd task setup'd
		move.b	donesigbit(PC),d1	; signal
		bset	d1,d0
		exec	Wait			;wait for this event
	;-- Wait for reply (main loop) ---------;
.mainloop	move.l	window(PC),a0		;window message?
		move.l	wd_UserPort(a0),a0	; ^message port
		exec	WaitPort
.nextmsg	move.l	window(PC),a0		;window message?
		move.l	wd_UserPort(a0),a0	; ^message port
		exec	GetMsg			; try to get it...
		tst.l	d0			; got one?
		beq.b	.mainloop		; nope: wait for next msg
	;---- got a window event ---------------;
		move.l	d0,a0			;^IDCMP-message -> a0
		cmp.l	#IDCMP_CLOSEWINDOW,im_Class(a0) ;close window?
		bne.b	.nextmsg		; no -> continue being idle ;)
	;-- Exit program -----------------------;
exit		move.l	surrtask(PC),a1		;Shut surround task
		moveq	#0,d0
		move.b	surrsigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
		moveq	#0,d0			;wait 'till 2nd task exited
		move.b	donesigbit(PC),d1	; signal
		bset	d1,d0
		exec	Wait			;wait for this event
error7		move.l	window(PC),a0		;Close output window
		intui	CloseWindow
error6		move.b	donesigbit(PC),d0
		exec	FreeSignal
error5		move.l	buffer(PC),a1		;^Buffer
		move.l	#BUFSIZE*5,d0
		exec	FreeMem
error4		move.l	dosbase(PC),a1		;close dos library
		exec	CloseLibrary
error3		move.l	intuibase(PC),a1	;close intuition library
		exec	CloseLibrary
error2		move.l	maestbase(PC),a1	;close maestix library
		exec	CloseLibrary
error1		moveq	#0,d0			;Reply 0
		rts				;back to CLI

*---------------------------------------------------------------*
*	== SURROUND PROCESS ==					*
*								*
SurroundProc
	;-- Get exiting signal -----------------;
		sub.l	a1,a1			;Get task structure
		exec	FindTask
		move.l	d0,surrtask
		moveq	#-1,d0			;get sig bit
		exec	AllocSignal
		move.b	d0,surrsigbit
		cmp.b	#-1,d0			;got no bit
		beq	.error1
		move.l	maintask(PC),a1		;task is done
		moveq	#0,d0
		move.b	donesigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
	;-- Allocate Maestro -------------------;
		sub.l	a0,a0			;no tags
		maest	AllocMaestro
		move.l	d0,maestro		;^Maestro base
		beq	.error2
	;-- Set Modus --------------------------;
		move.l	maestro(PC),a0		;^Maestro base
		lea	modustags(PC),a1	;^Modus tags
		maest	SetMaestro		;set it now
	;-- Read Status ------------------------;
		move.l	maestro(PC),a0		;^Maestro base
		move.l	#MSTAT_Signal,d0	;is input signal ok?
		maest	GetStatus		;get the card status
		tst.l	d0
		beq	.error3
	;-- Create Messageports ----------------;
		exec	CreateMsgPort		;create a messageport
		move.l	d0,rport		; as receive port
		beq	.error3
		exec	CreateMsgPort		;create a messageport
		move.l	d0,tport		; as transmit port
		beq	.error4
	;-- Init messages ----------------------;
		move.l	rport(PC),d1		;^Receive Reply Port
		move.l	tport(PC),d2		;^Transmit Reply Port
		lea	msg1(PC),a0		;^1st Message
		lea	msg2(PC),a1
		lea	msg3(PC),a2
		lea	msg4(PC),a3
		lea	msg5(PC),a4
		move.l	buffer(PC),d0		;get buffer ptr
		move.l	d0,(dmn_BufPtr,a0)	; set buffer 1
		add.l	#BUFSIZE,d0
		move.l	d0,(dmn_BufPtr,a1)	; set buffer 2
		add.l	#BUFSIZE,d0
		move.l	d0,(dmn_BufPtr,a2)	; set buffer 3
		add.l	#BUFSIZE,d0
		move.l	d0,(dmn_BufPtr,a3)	; set buffer 4
		add.l	#BUFSIZE,d0
		move.l	d0,(dmn_BufPtr,a4)	; set buffer 5
		move.l	#BUFSIZE,(dmn_BufLen,a0) ;Set buffer length
		move.l	#BUFSIZE,(dmn_BufLen,a1)
		move.l	#BUFSIZE,(dmn_BufLen,a2)
		move.l	#BUFSIZE,(dmn_BufLen,a3)
		move.l	#BUFSIZE,(dmn_BufLen,a4)
		move.l	d1,(MN_REPLYPORT,a0)	;Set Reply-Port
		move.l	d1,(MN_REPLYPORT,a1)
		move.l	d2,(MN_REPLYPORT,a2)
		move.l	d2,(MN_REPLYPORT,a3)
		move.l	d2,(MN_REPLYPORT,a4)
		move	#dmn_SIZEOF,(MN_LENGTH,a0) ;Set msg length
		move	#dmn_SIZEOF,(MN_LENGTH,a1)
		move	#dmn_SIZEOF,(MN_LENGTH,a2)
		move	#dmn_SIZEOF,(MN_LENGTH,a3)
		move	#dmn_SIZEOF,(MN_LENGTH,a4)
	;-- Start receive process --------------;
		move.l	maestro(PC),a0		;transmit msg to library
		lea	msg1(PC),a1
		maest	ReceiveData		; the 1st (starts receiver!)
		move.l	maestro(PC),a0
		lea	msg2(PC),a1
		maest	ReceiveData		; and the 2nd
		move.l	maestro(PC),a0
		lea	msg3(PC),a1
		maest	TransmitData		; and the 3rd
		move.l	maestro(PC),a0
		lea	msg4(PC),a1
		maest	TransmitData		; and the 4th
		move.l	maestro(PC),a0
		lea	msg5(PC),a1
		maest	TransmitData		; and the 5th
	;-- wait for messages ------------------;
.mainloop	move.l	tport(PC),a0		;maestix message?
		exec	GetMsg			; try to get it...
		tst.l	d0			; got one?
		bne.b	.gottransmit		; then evaluate it
		move.l	rport(PC),a0		;receive message?
		exec	GetMsg
		tst.l	d0
		bne.b	.gotreceive
		moveq	#0,d0			;create wait mask
		move.b	surrsigbit(PC),d1	; signal for exiting
		bset	d1,d0
		move.l	rport(PC),a0		; second, from receive port
		move.b	MP_SIGBIT(a0),d1	; sig bit
		bset	d1,d0			; set this bit
		move.l	tport(PC),a0		; last, from transmit port
		move.b	MP_SIGBIT(a0),d1
		bset	d1,d0
		exec	Wait			;wait for these events
		move.b	surrsigbit(PC),d1	; exit forced?
		btst	d1,d0			; test this bit
		beq.b	.mainloop		;not wanted -> main loop
		bra.b	.exit			; wanted -> leave
	;---- got a transmitter event ----------;
.gottransmit	move.l	maestro(PC),a0		;Re-send message
		move.l	d0,a1
		move.l	rport(PC),(MN_REPLYPORT,a1) ;Set Reply-Port
		maest	ReceiveData		; to maestix library
		bra.b	.mainloop
	;---- got a receive event --------------;
.gotreceive	bsr	surround		;do the surround
		bra.b	.mainloop		;and try again
	;-- Leave task -------------------------;
.exit		move.l	maestro(PC),a0		;Flush all messages
		maest	FlushTransmit
		move.l	maestro(PC),a0
		maest	FlushReceive
		move.l	tport(PC),a0		;delete transmit port
		exec	DeleteMsgPort
.error4		move.l	rport(PC),a0		;delete receive port
		exec	DeleteMsgPort
.error3		move.l	maestro(PC),a0		;Set maestro free
		maest	FreeMaestro
.error2		move.l	maintask(PC),a1		;task is done
		moveq	#0,d0
		move.b	donesigbit(PC),d1
		bset	d1,d0
		exec	Signal			; signals the exit
.error1		rts				;done (freed by DOS)

*-------------------------------------------------------*
*  surround	calculate surround data			*
*	-» D0.l	^Maestro Msg				*
*							*
surround	move.l	d0,a1			;get ptr
	;-- Get pointers -----------------------;
		move.l	dmn_BufPtr(a1),a0	;a0: ^received data
		move.l	dmn_BufLen(a1),d0
		lea	(a0,d0.l),a2		;a2: ^end of buffer
	;-- Surrounding ------------------------;
.loop		move	(a0),d0			;left word
		ext.l	d0
		move	2(a0),d1		;right word
		ext.l	d1
		sub.l	d1,d0			;difference
		asr.l	#1,d0
		move	d0,(a0)+
		move	d0,(a0)+
		cmp.l	a2,a0			;end reached?
		blo.b	.loop
	;-- Send buffer to transmitter ---------;
		move.l	maestro(PC),a0		;Send message
		move.l	tport(PC),(MN_REPLYPORT,a1) ;Set Reply-Port
		maest	TransmitData		; to transmitter
	;-- Done -------------------------------;
		rts

*---------------------------------------------------------------*
*	== DATA SECTION ==					*
*								*
maintask	dc.l	0			;^Main task
surrtask	dc.l	0			;^Surround task
surrsigbit	dc.b	0			;Surround task signal bit
donesigbit	dc.b	0			;Main task done sigbit
		even
maestbase	dc.l	0			;^Maestix Lib Base
intuibase	dc.l	0			;^Intuition Lib Base
dosbase		dc.l	0			;^DOS Lib Base
maestro		dc.l	0			;^Maestro Base
rport		dc.l	0			;^Receive MsgPort
tport		dc.l	0			;^Transmit MsgPort
buffer		dc.l	0			;^Data buffer
window		dc.l	0			;^Window structure
msg1		ds.b	dmn_SIZEOF		;^first message
msg2		ds.b	dmn_SIZEOF		;^second message
msg3		ds.b	dmn_SIZEOF		;^third message
msg4		ds.b	dmn_SIZEOF		;^fourth message
msg5		ds.b	dmn_SIZEOF		;^fifth message

modustags	dc.l	MTAG_Input,INPUT_STD	;use standard input
		dc.l	MTAG_Output,OUTPUT_FIFO
		dc.l	MTAG_CopyProh,CPROH_OFF
		dc.l	MTAG_Emphasis,EMPH_OFF
		dc.l	MTAG_Source,SRC_INPUT
		dc.l	MTAG_Rate,RATE_INPUT
		dc.l	TAG_DONE

tasktags	dc.l	NP_Entry,SurroundProc	;<- New process' tags
		dc.l	NP_Priority,30
		dc.l	NP_Name,.name
		dc.l	TAG_DONE
.name		dc.b	"Maestix surround process",0
		even

windowtags	dc.l	WA_IDCMP,IDCMP_CLOSEWINDOW ;<- New window's tags
		dc.l	WA_Title,.title
		dc.l	WA_InnerWidth,150
		dc.l	WA_InnerHeight,0
		dc.l	WA_DragBar,-1
		dc.l	WA_DepthGadget,-1
		dc.l	WA_CloseGadget,-1
		dc.l	WA_Activate,-1
		dc.l	WA_RMBTrap,-1
		dc.l	TAG_DONE
.title		dc.b	"Surround generator",0
		even

maestname	dc.b	"maestix.library",0	;Maestix name
intuiname	dc.b	"intuition.library",0	;Intuition name
dosname		dc.b	"dos.library",0		;DOS name
		even

*---------------------------------------------------------------*
*	== END ==						*
*								*
		END
