song		=$60000

		SECTION	replaydemo,code
* REPLAY-DEMO
		move	#$4000,$dff09a
		lea	song,a0
		jsr	mt_init(pc)
m		cmp.b	#155,$dff006
		bne.s	m
		move	#$0f0,$dff180
		jsr	mt_play(pc)
		move	#$06d,$dff180
		btst	#6,$bfe001
		bne.s	m
m2		cmp.b	#154,$dff006		; Song ausfaden lassen
		bne.s	m2
		jsr	mt_play(pc)
		subq	#1,mt_allvol		; Bis Gesamtlautstärke
		bne	m2			; =0 ist
		jsr	mt_end(pc)
		move	#$c000,$dff09a
		moveq	#0,d0
		rts
************************
*       SYNTRACKER     *
*          1.70        *
*     -r-e-p-l-a-y-    *
************************
* Coded by Twice / RAVE (Last change: Sun,26-Jul-92 19:04)
* ® 1992 by RAVE !!
* Any questions ?? Then
* call: 04298-4873 &
* ask for Bastian !
* -- -- -- -- -- -- -- -
* a0=Adresse des Moduls
* Man kann also durchaus mehrere Module im Speicher haben,
* und alle mit der gleichen Replayroutine abspielen !!
* Rasttime: 10-30 Rows (only Samples) 10-50 Rows (Samples&Syn)
mt_speeddefault		=6
mt_arpspeeddefault	=1
MT_INIT
		move	16(a0),mt_maxpos
		lea	1044(a0),a1
		move.l	a1,mt_samplelist
		lea	1556(a0),a1
		move.l	a1,mt_patternlists
		lea	2580(a0),a1
		move.l	a1,mt_patterndata
		lea	2580(a0),a1
		moveq.l	#0,d0
		move	18(a0),d0		; Maxpats
		addq	#1,d0
		lsl.l	#7,d0
		add.l	d0,a1
		move.l	a1,mt_waveforms
		lea	mt_datasstart,a0
mt_clrsoundstatics
		clr.b	(a0)+
		cmp.l	#mt_datasend,a0
		bne.s	mt_clrsoundstatics	

		move	#mt_speeddefault,mt_speed ; Defaultspeed
		move	#mt_arpspeeddefault,mt_arpeggiospeed+mt_datas
		move	#mt_arpspeeddefault,mt_arpeggiospeed+mt_datas+(mt_datasize*1)
		move	#mt_arpspeeddefault,mt_arpeggiospeed+mt_datas+(mt_datasize*2)
		move	#mt_arpspeeddefault,mt_arpeggiospeed+mt_datas+(mt_datasize*3)
		move	#$ff,mt_allvol
		move	#$000f,$dff096
		jsr	mt_clrchannels(pc)	; Kanäle aus
		move	#300,d0
mt_initwait	dbf	d0,mt_initwait
		move	#$800f,$dff096		; Kanäle an
		move	#$00ff,$dff09e		; keine Modulationen
		bset	#1,$bfe001		; Filter aus
		rts
MT_PLAY					; Jeden Frame einmal aufrufen
		movem.l	d0-d7/a0-a6,-(A7)

		addq	#1,mt_count
		move	mt_speed,d0
		cmp	mt_count,d0
		bne	mt_notnewnote
		clr	mt_count
		cmp	#-1,mt_break
		beq.s	mt_nobreak
		move	mt_break,mt_pos		; Wohin brechen ??
		clr	mt_patternpos		; Anfang des Pats
		move	#-1,mt_break		; Erledigt
mt_nobreak	

		lea	$dff0a0,a4
		lea	realwavech1,a5		; Waveform-Playbuffer
		lea	mt_datas,a2
		move.l	mt_patternlists,a0
		move	#$0001,mt_channelx
		jsr	mt_getnote(pc)
		lea	$dff0b0,a4
		lea	realwavech1+32,a5
		lea	mt_datas+mt_datasize,a2
		move.l	mt_patternlists,a0
		lea	128(a0),a0
		move	#$0002,mt_channelx
		jsr	mt_getnote(pc)
		lea	$dff0c0,a4
		lea	realwavech1+64,a5
		lea	mt_datas+(2*mt_datasize),a2
		move.l	mt_patternlists,a0
		lea	256(a0),a0
		move	#$0004,mt_channelx
		jsr	mt_getnote(pc)
		lea	$dff0d0,a4
		lea	realwavech1+96,a5
		lea	mt_datas+(3*mt_datasize),a2
		move.l	mt_patternlists,a0
		lea	384(a0),a0
		move	#$0008,mt_channelx
		jsr	mt_getnote(pc)

; Trackcnt. erhoehen
		addq	#4,mt_patternpos	; Next patpos
		cmp	#128,mt_patternpos	; Patternend ??
		bne.s	mt_notnewpattern
		clr	mt_patternpos		; Start new pat !!
		addq	#1,mt_pos		; Next position
		move	mt_maxpos,d0		; Last pos
		cmp	mt_pos,d0		; reached
		bne.s	mt_notrestartsong	;   ??
		clr	mt_pos			; First pos !!
mt_notrestartsong
mt_notnewpattern
mt_notnewnote
* Arpeggio
		lea	mt_datas,a2
		lea	$dff0a0,a1
		jsr	mt_arpeggio(pc)
		lea	mt_datas+mt_datasize,a2
		lea	$dff0b0,a1
		jsr	mt_arpeggio(pc)
		lea	mt_datas+(2*mt_datasize),a2
		lea	$dff0c0,a1
		jsr	mt_arpeggio(pc)
		lea	mt_datas+(3*mt_datasize),a2
		lea	$dff0d0,a1
		jsr	mt_arpeggio(pc)
* 'Stotter'-Effekt
* Wert von akt. Lautstaerke abziehen
		lea	mt_datas,a3
		lea	$dff0a8,a4
		jsr	mt_stotter(pc)
		lea	mt_datas+mt_datasize,a3
		lea	$dff0b8,a4
		jsr	mt_stotter(pc)
		lea	mt_datas+(2*mt_datasize),a3
		lea	$dff0c8,a4
		jsr	mt_stotter(pc)
		lea	mt_datas+(3*mt_datasize),a3
		lea	$dff0d8,a4
		jsr	mt_stotter(pc)
* ADSR-KURVE
		lea	mt_datas,a3
		jsr	mt_adsr(pc)
		move	d1,$dff0a8
		lea	mt_datas+mt_datasize,a3
		jsr	mt_adsr(pc)
		move	d1,$dff0b8
		lea	mt_datas+(2*mt_datasize),a3
		jsr	mt_adsr(pc)
		move	d1,$dff0c8
		lea	mt_datas+(3*mt_datasize),a3
		jsr	mt_adsr(pc)
		move	d1,$dff0d8


* SMOOTH
		lea	mt_datas,a3
		lea	wavech1,a4		; Adresse akt. Wellenform Channel 1
		jsr	mt_smooth(pc)
		lea	mt_datas+mt_datasize,a3
		lea	wavech1+32,a4
		jsr	mt_smooth(pc)
		lea	mt_datas+(2*mt_datasize),a3
		lea	wavech1+64,a4
		jsr	mt_smooth(pc)
		lea	mt_datas+(3*mt_datasize),a3
		lea	wavech1+96,a4
		jsr	mt_smooth(pc)

* Waveformmix
		lea	wavech1,a4		; Operation Buffer
		lea	mt_datas,a3
		jsr	mt_mix(pc)
		lea	wavech2,a4		; Operation Buffer
		lea	mt_datas+mt_datasize,a3
		jsr	mt_mix(pc)
		lea	wavech3,a4		; Operation Buffer
		lea	mt_datas+(2*mt_datasize),a3
		jsr	mt_mix(pc)
		lea	wavech4,a4		; Operation Buffer
		lea	mt_datas+(3*mt_datasize),a3
		jsr	mt_mix(pc)


; Sample evt.l starten
		lea	mt_datas,a2
		lea	$dff0a0,a4
		moveq	#4-1,d7
mt_sampleop	tst	mt_samplelen(a2)
		beq.s	mt_nextsampleop
		move.l	mt_sampleadr(a2),(a4)
		move	mt_samplelen(a2),4(a4)
		clr	mt_samplelen(a2)
mt_nextsampleop	lea	mt_datasize(a2),a2
		lea	$10(a4),a4
		dbf	d7,mt_sampleop
		move	#$800f,$dff096		; Alle Kanäle an

* COPY EDITBUFFERS INTO PLAYBUFFERS		; Wird gleichzeitig
		lea	wavech1,a0		; als DMA-Wartepause
		lea	realwavech1,a1		; benutzt
		REPT	128/4
		move.l	(a0)+,(a1)+
		ENDR		
; Samplerepeat evt.l starten
		lea	mt_datas,a2
		lea	$dff0a0,a4
		moveq	#4-1,d7
mt_repeatop	tst	mt_repeatlen(a2)
		beq.s	mt_nextrepeatop
		move.l	mt_repeatadr(a2),(a4)
		move	mt_repeatlen(a2),4(a4)
		clr	mt_repeatlen(a2)
mt_nextrepeatop	lea	mt_datasize(a2),a2
		lea	$10(a4),a4
		dbf	d7,mt_repeatop

mt_PLAYEND	movem.l	(a7)+,d0-d7/a0-a6
		rts
; Effectrouts
; Version : 3.09  -- 25-Jun-92
MT_MIX		
		move.l	mt_adsr_ptr(a3),a0	; Pointer on Effectdats
		cmp.l	#0,a0			; Is it a sample ??
		beq	mt_dothenextmix
		lea	-32(a0),a6		; Adress of wave
		moveq.l	#0,d0
		move.b	mt_mixspeed+1(a3),d0	; Wavemixspeed
		beq	mt_wavemixnone		; No Mix and next Channel
		clr.b	mt_synmode+1(a3)	; No 'Copywave'
		addq.b	#1,mt_mixcount+1(a3)
		cmp.b	mt_mixcount+1(a3),d0	; Do the next Mix
		bge	mt_dothenextmix		; and
		clr.b	mt_mixcount+1(a3)	; increase
		move.b	mt_mixdir+1(a3),d0
		add.b	d0,mt_mixoffset+1(a3)	; Mix offset ??!!
		and	#31,mt_mixoffset(a3)
		move.b	20(a0),d0		; Startoffset erreicht ??
		cmp.b	mt_mixoffset+1(a3),d0
		bne.s	mt_notbackmode2
		tst.b	22(a0)
		bpl.s	mt_notbackmode2
		move.b	#1,mt_mixdir+1(a3)
		bra.s	mt_nohole
mt_notbackmode2	move.b	21(a0),d0		; Mixholestart ??
		cmp.b	mt_mixoffset+1(a3),d0
		bne.s	mt_nohole
		move.b	22(a0),d0
		bpl.s	mt_notbackmode
		move.b	#-1,mt_mixdir+1(a3)
		bra.s	mt_nohole
mt_notbackmode	add.b	d0,mt_mixoffset+1(a3)
		and	#31,mt_mixoffset(a3)
mt_nohole	move.b	24(a0),d0		; Mixwave (OFFSET !)
		lsl.l	#6,d0
		move.l	mt_waveforms,a1
		add.l	d0,a1
		move.l	a1,d2
		move.l	d2,d0
		add	#32,d2			; End of Mixwave
		add	mt_mixoffset(a3),a1	; Offset
mt_wavestartmixing
		moveq	#32-1,d6		; Whole Wave !
mt_wavemix	cmp.l	d2,a1			; End of Mixwave ??
		bne.s	mt_notmixwaveend
		move.l	d0,a1			; Start of Mixwave !!
mt_notmixwaveend
		move.b	(a6)+,d4		; Byte from Orig. Wave
		move.b	(a1)+,d5		; Byte from Mix. Wave
		bmi.s	mt_mixok
		move.b	d5,d4
mt_mixok	move.b	d4,(a4)+		; Write into Ed.Buffer
		dbf	d6,mt_wavemix		; Do all bytes !
mt_dothenextmix	rts
mt_wavemixnone	
		cmp.b	#1,mt_synmode+1(a3)
		bne	mt_dothenextmix
		clr	mt_synmode(a3)
		moveq	#32-1,d6
mt_copywavemix	move.b	(a6)+,(a4)+
		dbf	d6,mt_copywavemix
		bra	mt_dothenextmix

MT_SMOOTH	cmp	#8,mt_smoothstep(a3)	; Smooth beendet ??
		beq.s	mt_smoothnextchannel	; Smooth-Counter
		move.l	mt_adsr_ptr(a3),a0	; Zeiger auf
		addq.l	#8,a0			; Smoothdats
		add	mt_smoothstep(a3),a0	; Akt. Step
		move	mt_smoothcount(a3),d0 ; Step abgearbeitet ??
		cmp.b	(a0),d0
		bne.s	mt_smoothnotnextstep
		clr	mt_smoothcount(a3)
		addq	#2,mt_smoothstep(a3)	; Naechster Step
		bra.s	mt_smooth		; Nochmal mit neuem Step
mt_smoothnotnextstep
		addq	#1,mt_smoothcount(a3)
		moveq	#0,d0
		moveq	#0,d2
		move.b	1(a0),d0		; Angleichfaktor
		move.b	31(a4),d2		; Das Ende knuepft an den Anfang an
		moveq	#0,d6			; Sampleoffset
mt_smoothwholesamp
		move.b	(a4,d6),d1		; Samplewert
		ext	d1
		sub	d1,d2			; Distanz
		muls	d0,d2			; Wiegross
		asr	#7,d2			; bleibt die Distanz ($7f bleibt sie gleich !)
		add	d1,d2			; wieder dazu
		move.b	d2,(a4,d6)		; zurueckschreiben und naechster Wert !!
		addq	#1,d6
		cmp	#32,d6
		bne.s	mt_smoothwholesamp
mt_smoothnextchannel
		rts

MT_ADSR	
		tst.l	mt_adsr_ptr(a3)		; Sample ??
		beq	mt_noadsr
		cmp	#8,mt_adsrstep(a3)	; Adsr ende ??
		beq.s	mt_noadsrchange
		move.l	mt_adsr_ptr(a3),a0 	; Zeiger auf Adsr-Tabelle
		add	mt_adsrstep(a3),a0	; Akt. Adsr-Byte
		move.b	(a0),d0
		cmp.b	mt_adsrcount+1(a3),d0	; Naechster Step ??
		bne.s	mt_notnextadsrstep
		clr	mt_adsrcount(a3)
		addq	#2,mt_adsrstep(a3)	; Naechster Step !!
		bra.s	mt_adsr
mt_notnextadsrstep
		addq	#1,mt_adsrcount(a3)
		move.b	mt_adsr_percent+1(a3),d1
		move.b	1(a0),d0		; Adsrval
		cmp	#2,mt_adsrstep(a3)
		beq.s	mt_adsrsub
		cmp	#6,mt_adsrstep(a3)
		beq.s	mt_adsrsub
		add.b	d0,d1
		cmp.b	#$3f,d1
		ble.s	mt_adsrchange
		move.b	#$3f,d1
		bra.s	mt_adsrchange
mt_adsrsub	sub.b	d0,d1
		bpl.s	mt_adsrchange
		clr.b	d1
mt_adsrchange	move.b	d1,mt_adsr_percent+1(a3)
mt_noadsrchange	move	mt_volume(a3),d0	; Lautstaerke
		move	mt_adsr_percent(a3),d1	; Prozent
		and	#%00111111,d1
		mulu	d0,d1
		lsr	#6,d1		; runtertransformieren
mt_nextadsr	mulu	mt_allvol,d1
		lsr	#8,d1
		rts
mt_noadsr	move	mt_volume(a3),d1
		bra	mt_nextadsr

MT_STOTTER	move	mt_volume(a3),d0	; Act. Volume
		sub	mt_subvolper(a3),d0	; is it still
		bpl.s	mt_svp_stillok		; a possible value ??
		moveq	#0,d0			; under zero ? Then volume=0
mt_svp_stillok	move	d0,mt_volume(a3)	; Save
		rts

MT_ARPEGGIO	move.l	mt_vib(a2),a0		; Vibrato-Pointer
		add	mt_vib_off(a2),a0
		addq	#1,mt_arpeggiocount(a2)
		move.b	mt_arpeggiospeed+1(a2),d0
		cmp.b	mt_arpeggiocount+1(a2),d0
		bne.s	mt_vibratorout		
		clr.b	mt_arpeggiocount+1(a2)
		move	mt_arpeggiostep(a2),d0
		beq.s	mt_arpeggio1
		cmp	#1,d0
		beq.s	mt_arpeggio2
		
		move	mt_per_3(a2),d0
		clr	mt_arpeggiostep(a2)
		bra.s	mt_nextarpeggio
mt_arpeggio2
		move	mt_per_2(a2),d0
		move	#2,mt_arpeggiostep(a2)
		bra.s	mt_nextarpeggio
mt_arpeggio1
		move	mt_per_1(a2),d0
		move	#1,mt_arpeggiostep(a2)
mt_nextarpeggio
		move	d0,mt_oldarp(a2)
mt_vibratorout
		move	mt_oldarp(a2),d0
		move	mt_vib_percent(a2),d1	; Vibrato-Staerke
		beq.s	mt_novibrato
		
		lea	mt_periodtab,a3		; Akt. Periode suchen
		moveq.l	#0,d2
		move	mt_actper(a2),d2	; Von Grundton an
		add	d2,d2	
		add.l	d2,a3
mt_searchper	cmp	(a3)+,d0		; Muß maximal 15 Worte
		bne.s	mt_searchper		; durchlaufen
		moveq	#0,d2
		move.b	(a0),d2			; Aktueller Vibrato-Wert
		bpl.s	mt_vibrpos		; Vibrato negativ ??
		neg.b	d2			; Negieren !!
		mulu	d1,d2			; Prozent*Wert
		lsr	#7,d2			; runtertransformieren
		move	-4(a3),d3		; Vorige Periode
		move	d3,d4			; Orig. Periode
		sub	d0,d4			; Differenz zur vorigen
		mulu	d2,d4			; wieviel
		lsr	#5,d4		; Prozent blieben wohl stehen ??!!
		add	d4,d0		; Differenz von Orig.Periode abziehen
		bra.s	mt_vibrneg
mt_vibrpos	mulu	d1,d2			; Prozent*Wert
		lsr	#7,d2			; runtertransformieren
		move	(a3),d3			; Naechste Periode
		move	d0,d4			; Differenz zwischen orig.
		sub	d3,d4			; und naechsten Periode
		mulu	d2,d4
		lsr	#5,d4
		sub	d4,d0
mt_vibrneg
		move	mt_vib_speed(a2),d1
		add	d1,mt_vib_off(a2)
		and	#%00011111,mt_vib_off(a2)
mt_novibrato
		move	mt_slideper(a2),d1
		add	d1,mt_actport(a2)
		add	mt_actport(a2),d0	; Portamento noch dazu
		move	d0,$6(a1)		; audxper
mt_noarpeggio_x	rts


* STOP MUSIK
mt_end
		clr	mt_datas
		clr	mt_datas+mt_datasize
		clr	mt_datas+(2*mt_datasize)
		clr	mt_datas+(3*mt_datasize)		
mt_clrchannels	
		move	#$000f,$dff096
		move	#300,d0
mt_wait2	dbf	d0,mt_wait2
		move.l  #mt_leerdata,$dff0a0
		move.l	#$001003e8,$dff0a4
		clr	$dff0a8
		move.l	#mt_leerdata,$dff0b0
		move.l	#$001003e8,$dff0b4
		clr	$dff0b8
		move.l	#mt_leerdata,$dff0c0
		move.l	#$001003e8,$dff0c4
		clr	$dff0c8
		move.l	#mt_leerdata,$dff0d0
		move.l	#$001003e8,$dff0d4
		clr	$dff0d8
		rts
* a0=Adresse der Patternliste
* a1 wird gebraucht
* a2=mt_datas
* (a3),(a4),(d7)
* ------------------------------------------------------------------
mt_oldinstr	move.b	mt_oldinstrnr+1(a2),d1
		bra	mt_newinstr
mt_getnote	
		moveq	#0,d0
		add	mt_pos,a0		; rausfinden
		move.b	512(a0),d1		; Transpose
		move.b	d1,mt_transposework+1
		move.b	(a0),d0			; aktueller Pattern
		lsl	#7,d0			; *128 (Patterngroeße)
		move.l	mt_patterndata,a0	; Adresse des 1.Patterns
		add	d0,a0			; Offset addieren
		add	mt_patternpos,a0	; Offset innerhalb des Patterns
; in a0 steht jetzt die Adresse der aktuellen Notenzeile
		cmp.b	#$40,1(a0)
		bge.s	mt_futmix
		moveq	#0,d0
		move.b	(a0),d0
		beq	mt_oldnote		; Pause ??
		add.b	d1,d0			; +Transpose
		subq.b	#1,d0
		tst.b	d0
		bge.s	mt_transposeok		; Unter tiefstem Ton ??
		moveq	#0,d0			; tiefster Ton
mt_transposeok	
		move	d0,mt_actper(a2)
		add	d0,d0
		lea	mt_periodtab,a1		; Periodentabelle
		move	0(a1,d0),d0
		move	d0,mt_per_1(a2)	; 3 Perioden-Werte eintragen
		move	d0,mt_per_2(a2) ; (für Arpeggio)
		move	d0,mt_per_3(a2)
		move	d0,mt_oldarp(a2)	; Falls Arp. abgeschaltet ist
		clr	mt_slideper(a2)		; Kein sliden
		clr	mt_actport(a2)		; Portamento zuruecksetzen
; HIER EVTL. EQUALIZER NEU SETZEN !!
; move	mt_channelx,d1
; Bit 0=1 :Channel 1 new note
; Bit 1=1 :Channel 2   || 
; Bit 2=1 :Channel 3   ||
; Bit 3=1 :Channel 4   ||

		moveq	#0,d1
		tst.b	1(a0)
		beq	mt_oldinstr
		cmp.b	#$ff,1(a0)		; Instrument neu setzen,aber nicht neu anschlagen
		beq	mt_oldinstr_no_adsr

		cmp.b	#$40,1(a0)
		blt.s	mt_032

mt_futmix	cmp.b	#$4f,1(a0)		: Größer als $4f ??
		bgt	mt_oldinstr_no_adsr
		moveq.l	#0,d0			: Dazwischen...
		move.b	1(a0),d0		; Adresse der
		sub.b	#$40,d0			; neuen
		move.l	mt_samplelist,a1	; Wellenform
		lsl.l	#4,d0			: setzen
		add.l	d0,a1
		move.l	(a1),a1
		add.l	mt_waveforms,a1
		lea	32(a1),a1
		move.l	a1,mt_adsr_ptr(a2)
		move	#1,mt_synmode(a2)
		move.l	a5,mt_sampleadr(a2)
		bra	mt_oldinstr_no_adsr

mt_032		cmp.b	#$20,1(a0)
		bgt	mt_oldinstr_no_adsr


		move.l	#mt_vibrato,mt_vib(a2)
		clr	mt_vib_off(a2)
		clr.b	mt_vib_percent+1(a2)

		move.b	1(a0),d1
		move.b	d1,mt_oldinstrnr+1(a2)
mt_newinstr
		subq.b	#1,d1			; 0 ist schon belegt

		move.l	mt_samplelist,a1
		cmp	#16,d1
		bge	mt_itsasample

mt_asynthetic	lsl.l	#4,d1			; *16
		move	mt_channelx,d2		; DMA-Kanal aus
		move	d2,$dff096		; ausschalten
		move.l	a5,mt_sampleadr(a2)	; Adresse setzen				
		move.b	#1,mt_synmode+1(a2)	; Copy wave to Buff
		move	4(a1,d1),mt_samplelen(a2)
		move	6(a1,d1),mt_vol(a2)
		move	#$3f,d0
		mulu	mt_vol(a2),d0
		lsr	#6,d0
		move	d0,mt_volume(a2)

		move.l	0(a1,d1),a1		; Offset of wave
		add.l	mt_waveforms,a1		; +Start of waveforms
		lea	32(a1),a1		; Adress of ADSR
		move.l	a1,mt_adsr_ptr(a2)	; ADSR-Ptr
		move.b	16(a1),d0		; Vibrato
		move.b	d0,d1
		and.b	#$f0,d0
		lsr.b	#4,d0
		move.b	d0,mt_vib_speed+1(a2)
		and.b	#$0f,d1
		move.b	d1,mt_vib_percent+1(a2)
		moveq.l	#0,d1
		move.b	18(a1),d1		; Vibrato-Wavenr
		lsl.l	#6,d1			; *Wavestructsize
		add.l	mt_waveforms,d1
		move.l	d1,mt_vib(a2)
		move.b	#1,mt_mixdir+1(a2)
		move.b	20(a1),mt_mixoffset+1(a2)
		move.b	17(a1),mt_mixspeed+1(a2)
		move.b	17(a1),mt_mixcount+1(a2) ; damit die Waveform gleich gespielt wird
		beq.s	mt_mixnomix
		subq	#1,mt_mixcount(a2)
mt_mixnomix	clr.b	mt_adsrstep+1(a2)	; Beginn Adsr
		clr.b	mt_smoothstep+1(a2)	; Beginn Smooth
		bra	mt_itsasyntetic2
mt_itsasample
		move	mt_channelx,d2		; DMA-Kanal aus (damit neue Werte sofort uebenommen werden !)
		move	d2,$dff096		; ausschalten
; damit Daten beim Einschalten sofort übernommen werden !
		lsl.l	#4,d1
		move	4(a1,d1),d0		; Lenght of Sample
		bne.s	mt_notnosample
		move.l	#mt_leerdata,mt_sampleadr(a2)
		move	#1,mt_samplelen(a2)
		clr	$8(a4)
		bra.s	mt_repeatzero
mt_notnosample	move	d0,mt_samplelen(a2)
		move.l	0(a1,d1),d0		; Sample-Adresse
		add.l	mt_waveforms,d0		; +Start of waveforms
		add	8(a1,d1),d0		; +Samplestart
		move.l	d0,mt_sampleadr(a2)	; Set !
		move	6(a1,d1),mt_vol(a2)
		move	#$3f,d0
		mulu	mt_vol(a2),d0
		lsr	#6,d0
		move	d0,mt_volume(a2)
		move	12(a1,d1),d0		; Repeat-Len
		bne.s	mt_repeatnotzero
		move.l	#mt_leerdata,mt_repeatadr(a2)
		move	#1,mt_repeatlen(a2)
		bra	mt_repeatzero
mt_repeatnotzero move	d0,mt_repeatlen(a2)		; Repeat-Len
		move.l	0(a1,d1),d0		; Offset of wave
		add.l	mt_waveforms,d0		; +Start of waveforms
		add	10(a1,d1),d0		; Repeatstart
		move.l	d0,mt_repeatadr(a2)	; Set !
mt_repeatzero	clr.l	mt_adsr_ptr(a2)		; Keine adsr-kurve
		clr.l	mt_vib_percent(a2)	; Speed&Percent
		move.b	#8,mt_smoothstep+1(a2)	; Kein Smooth
		move.b	#8,mt_adsrstep+1(a2)	; Kein Adsr
		clr.b	mt_mixspeed+1(a2)
mt_itsasyntetic2
		clr.b	mt_subvolper+1(a2)
		clr.b	mt_smoothcount+1(a2)	; Smooth
		clr.l	mt_adsrcount(a2)	; zurueck (Count&Percent)
mt_oldnote
mt_oldinstr_no_adsr			; Instrument nicht neu anschlagen
		cmp.b	#"A",2(a0)
		bne.s	mt_noarpeggiovalues
		moveq	#0,d1
		lea	mt_periodtab,a1
		move	mt_actper(a2),d2
		beq	mt_fxok
		move	d2,d0
		move.b	3(a0),d1	; Effect-Value
		and.b	#$0f,d1		; untere 4-Bit bleiben stehen
		add	d1,d0
		add	d0,d0
		move	0(a1,d0.w),mt_per_2(a2)

		move	d2,d0
		move.b	3(a0),d1	; Effect-Value
		and.b	#$f0,d1		; untere 4-Bit bleiben stehen
		lsr.b	#4,d1
		add	d1,d0
		add	d0,d0
		move	0(a1,d0.w),mt_per_3(a2)
		rts
mt_noarpeggiovalues
		cmp.b	#"L",2(a0)
		bne.s	mt_notvolumechange
		moveq	#0,d0
		move.b	3(a0),d0			; new Volume
		mulu	mt_vol(a2),d0
		lsr	#6,d0				; /64
		move	d0,mt_volume(a2)		; Lautstaerke-Regelung Relativ von Max.Lautstaerke des Instruments
		rts
mt_notvolumechange
		cmp.b	#"M",2(a0)
		bne.s	mt_notchgmixspd
		move.b	3(a0),mt_mixspeed+1(a2)
		rts
mt_notchgmixspd	cmp.b	#"V",2(a0)
		bne.s	mt_notvibratopercent
		move.b	3(a0),d0
		move.b	d0,d1
		and.b	#$f0,d0
		lsr.b	#4,d0
		move.b	d0,mt_vib_speed+1(a2)
		and.b	#$0f,d1
		move.b	d1,mt_vib_percent+1(a2)
		move.l	#mt_vibrato,mt_vib(a2)
		rts
mt_notvibratopercent
		cmp.b	#"F",2(a0)
		bne.s	mt_notfilterchange
		tst.b	3(a0)
		bne.s	mt_filteron
		bset	#1,$bfe001
		rts
mt_filteron	bclr	#1,$bfe001
		rts
mt_notfilterchange
		cmp.b	#"S",2(a0)
		bne.s	mt_notspeedchange
		tst.b	3(a0)
		beq	mt_fxok
		move.b	3(a0),mt_speed+1
		rts
mt_notspeedchange
		cmp.b	#"O",2(a0)
		bne.s	mt_notarpeggiospeedchange
		tst.b	3(a0)
		beq	mt_fxok
		move.b	3(a0),mt_arpeggiospeed+1(a2)
		clr	mt_arpeggiocount(a2)
		rts
mt_notarpeggiospeedchange
		cmp.b	#"B",2(a0)
		bne.s	mt_notbreak
		tst.b	3(a0)		; Jump to next pos. ??
		bne.s	mt_notnextpat
		move	mt_pos,mt_break
		addq	#1,mt_break	; Next pos !
		move	mt_maxpos,d0	; Behind Song-End ??
		cmp	mt_break,d0
		bgt.s	mt_breakok
		clr	mt_break	; Then first Pos !!
		rts
mt_notnextpat
		clr	mt_break
		move.b	3(a0),mt_break+1 ; Dest. Pos
		move	mt_maxpos,d0
		cmp	mt_break,d0	; Behind Song-End ??
		bgt.s	mt_breakok	; Then abort !!
		move	#-1,mt_break
		rts
mt_breakok
mt_notbreak
		cmp.b	#"U",2(a0)
		bne.s	mt_notslideup
		moveq	#0,d0
		move.b	3(a0),d0
		move	mt_per_3(a2),d1
		sub	d0,d1
		cmp	#57,d1
		blt	mt_fxok
		sub	d0,mt_actport(a2)
		rts
mt_notslideup
		cmp.b	#"D",2(a0)
		bne.s	mt_notslidedown
		moveq	#0,d0
		move.b	3(a0),d0
		move	mt_per_1(a2),d1
		add	d0,d1
		cmp	#6832,d1
		bgt	mt_fxok
		add	d0,mt_actport(a2)
		rts
mt_notslidedown 
		cmp.b	#"G",2(a0)
		bne.s	mt_notsubvolumeper
		tst.b	1(a0)			; Instrnr.
		bne.s	mt_notnewvol
		move	#$3f,d0
		mulu	mt_vol(a2),d0
		lsr	#6,d0
		move	d0,mt_volume(a2)
mt_notnewvol	moveq	#0,d0
		move.b	3(a0),d0		; subvolper also has to
		mulu	mt_vol(a2),d0		; be relativ to Maxvolume !!
		lsr	#6,d0
		move	d0,mt_subvolper(a2)
		rts
mt_notsubvolumeper
		cmp.b	#"E",2(a0)
		bne.s	mt_notslide2note
		tst.b	(a0)			; Nicht bei Anschlag ??
		beq.s	mt_fxok
		addq.l	#4,a0			; Min. 1 Step
		moveq.l	#1,d0			; further on
		move.l	d7,-(a7)
		moveq	#124,d7			; Number of
		sub	mt_patternpos,d7	; Steps until
		lsr	#2,d7			; end of Pat
		subq	#1,d7			; dbf-loop !!
		bmi.s	mt_slideexit		; Last Pos ??
mt_searchnextnote
		tst.b	(a0)			; Note-Val
		bne.s	mt_nextnotefound
		addq.l	#4,a0
		addq	#1,d0			; Increase Step-Counter
		dbf	d7,mt_searchnextnote
		bra.s	mt_slideexit
mt_nextnotefound
		lea	mt_periodtab,a1
		moveq	#0,d1
		move.b	(a0),d1			; Act. note
		add.b	mt_transposework+1,d1
		add	d1,d1
		subq	#2,d1			; 0 is a dummy
		move	(a1,d1),d1		; Get Period
		move	mt_per_1(a2),d2		; act (source)-Per
		mulu	mt_speed,d0
		cmp	d1,d2
		bgt.s	mt_slidesourceisdeeper
		sub	d2,d1
		divu	d0,d1
		cmp.l	#$ffff,d1		; Rest ??
		ble.s	mt_slidenorest
		addq	#1,d1			; Aufrunden !
mt_slidenorest	move	d1,mt_slideper(a2)
		bra.s	mt_slideexit
mt_slidesourceisdeeper
		sub	d1,d2
		divu	d0,d2
		cmp.l	#$ffff,d2
		ble.s	mt_slidenorest2
		addq	#1,d2
mt_slidenorest2	neg	d2
		move	d2,mt_slideper(a2)
mt_slideexit	move.l	(a7)+,d7
mt_notslide2note
mt_fxok		rts
		
		SECTION	mt_publicdatas,data

* ------------SOUND-DATA-LISTS,PTR'S,COUNTERS-----------

mt_patterndata	ds.l	1		; Pattern-Daten-Ptr
mt_patternlists ds.l	1		; Adresse der Positionslisten
mt_samplelist	ds.l	1		; Tabelle der Samples + Laengen
mt_waveforms	ds.l	1		; Adresse der Waveforms

mt_maxpos	ds.w	1		; Maximal x Positionen
mt_datasstart
mt_allvol	dc.w	0		; Gesamt-Volume ($0-$ff)
mt_transposework dc.w	0
mt_break	dc.w	-1		; Jump to pos n
mt_count	ds.w	1		; immer bis mt_speed zaehlen,dann naechste Nte ausgeben
mt_speed	dc.w	6		; n*1/50 Sekunde Pause bis zur naechsten Note
mt_pos		ds.w	1		; Position-Counter
mt_patternpos	ds.w	1		; 0-124	(4 BYTES PRO NOTE !!!)
mt_patternposx	ds.w	1		; 0-20 (Cursor Positionen)
mt_channelx	ds.w	1		; Welcher Kanal gerade bearbeitet wird (in der Notendecodierroutine!)

mt_datasize	=$4a			; laenge dieser Datenlisten
mt_datas	ds.b	mt_datasize*4	; 4 Kanaele ....
mt_datasend				; Offsets von mt_datas
mt_volume		=$00		; Aktuelle Lautstaerke (relativ von mt_vol !)
mt_vol			=$02		; Max.Lautstaerke
mt_vib_percent		=$04
mt_vib_speed		=$06
mt_vib			=$08		; Pointer auf Vibrato-Tab
mt_vib_off		=$0c
mt_adsr_ptr		=$0e
mt_adsrstep		=$12
mt_adsrcount		=$14
mt_adsr_percent		=$16
mt_oldinstrnr		=$18
mt_per_1		=$1a		; fuer Arpeggio
mt_per_2		=$1c
mt_per_3		=$1e
mt_arpeggiostep		=$20	; Zeiger auf Arpeggio-Wert der gespielt wird
mt_arpeggiospeed	=$22
mt_arpeggiocount	=$24
mt_oldarp		=$26
mt_actper		=$28
mt_actport		=$2a
mt_smoothstep		=$2c		; Abflachschrittzaehler (insg 4 Stueck)
mt_smoothcount		=$2e		; Abflach-Zaehler (0-Smtcnt)
mt_mixdir		=$30
mt_mixspeed		=$32
mt_mixcount		=$34		; Offset fuer Mixwave
mt_mixoffset		=$36		; Offset added to Mixwave
mt_synmode		=$38		; Bit 0:Copy wave to Buff
mt_subvolper		=$3a		; Value to sub from Volume each frame
mt_slideper		=$3c		; Slide to next note
mt_sampleadr		=$3e
mt_samplelen		=$42
mt_repeatadr		=$44
mt_repeatlen		=$48

mt_periodtab
		dc.w	6832,6464,6096,5744,5424,5120,4832,4560,4304,4064,3840,3616	; Fuer Vibrato C-1
		dc.w	3416,3232,3048,2872,2712,2560,2416,2280,2152,2032,1920,1808
		dc.w	1708,1616,1524,1436,1356,1280,1208,1140,1076,1016,960,904
		dc.w	854,808,762,718,678,640,604,570,538,508,480,452
		dc.w	427,404,381,359,339,320,302,285,269,254,240,226
		dc.w	214,202,190,180,169,160,151,143,134,127,120,113
* Vibrato ±32 = ± 1 Halbnote
mt_vibrato
		dc.b 	000,024,047,069,088,104,116,123	; Sinus
		dc.b	126,125,119,108,094,076,055,032
		dc.b 	008,241,217,195,175,158,144,135
		dc.b	130,130,134,143,156,173,193,215
		even
		SECTION	song,data_c
mt_leerdata	ds.b	32
wavech1		ds.b	32
wavech2		ds.b	32
wavech3		ds.b	32
wavech4		ds.b	32
realwavech1	ds.b	128

		>EXTERN	"jo:synmod.tip tap tribe",song,-1
