
; ***********************************************************
; *                                                         *
; *                   B E E T H O V E N                     *
; *                                                         *
; *      R O U T I N E N  zum  E I N F U E G E N und        *
; *                                                         *
; *          A B S P I E L E N  von S O N G S in            *
; *                                                         *
; *          E I G E N E N   P R O G R A M M E N            *
; *                                                         *
; ***********************************************************
; *                                                         *
; *    Assembler-Source-Listing / Assembler: Devpac II      *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Im folgenden Assembler_Source_Listing finden Sie alle Routinen,
; die Sie benötigen, um Beethoven-Songs in eigene Programme einzubinden.
; Binden Sie die folgenden Routinen und die Definitionstabellen für
; die Variablen und Konstanten in Ihr eigenes Programm ein.
; Die Routinen sind zu vier Gruppen zusammengefaßt, die Sie jeweils
; mit 'bsr' aufrufen können.
; LOADSONG reserviert Speicher, läd Lieddaten und Instrumente,
; in a0 muß ein Zeiger auf den Filenamen übergeben werden
; GETSONG initialierst einen im Speicher stehenden Song,
; in a0 muß ein Zeiger auf die Songdaten und in d0 wenn möglich
; die Länge der Daten übergeben werden
; STARTMUSIK beginnt das Abspiel des Songs
; STOPMUSIK beendet das Abspiel des Songs
; DROPSONG gibt den Speicher wieder frei

; Wenn Sie mehrere Songs in Ihrem Programm verwenden, achten Sie darauf,
; daß Sie immer zuerst DROPSONG aufrufen, bevor Sie einen neuen Song
; mit LOADSONG laden (außer beim ersten mal). Bevor Sie STARTMUSIK
; aufrufen, müssen Sie jeweils erst LOADSONG ausgeführt haben
; und bevor Sie STOPMUSIK aufrufen müssen Sie erst STARTMUSIK aufgerufen
; haben. Und (tatsächlich !) bevor Sie DROPSONG aufrufen müssen Sie
; schließlich erst STOPMUSIK aufgerufen haben.

; Wenn Sie im Speicher stehenden Song mehrmals an- und ausschalten wollen,
; können Sie mehrmals abwechselnd STARTMUSIK und STOPMUSIK aufrufen.

; Also ... viel Glück und viel Erfolg wünscht Ihnen DAN DARK !


	XDEF	LOADSONG,GETSONG,STARTMUSIK,STOPMUSIK,DROPSONG


; Folgende Amiga-Betriebssystemroutinen werden von den nachfolgenden
; Routinen zum Laden und Abspielen von Songs benötigt

AddIntServer = -168	;exec-library
RemIntServer = -174
AllocMem = -198
FreeMem = -210
CloseLibrary = -414
OpenLibrary = -552
Open = -30		;dos-library
Close = -36
Read = -42
Lock = -84
UnLock = -90
Examine	= -102
CurrentDir = -126

	; *** Konstanten für CustomChip-Register ***

tasten = $BFEC01	; Register enthält Tastencode
dmacon = $DFF096	; Register für DMA ( direct memory access )
cialed = $BFE001	; Register für Tiefpassfilter ein/aus
aud0lch	= $DFF0A0
aud1lch	= $DFF0B0	; Soundregister, enthällt Zeiger ( für Paula )
aud2lch	= $DFF0C0	; auf die zu spielenden Samples
aud3lch	= $DFF0D0
aud0len	= $DFF0A4
aud1len	= $DFF0B4	; Soundregister, enthällt Länge ( für Paula )
aud2len	= $DFF0C4	; des zu spielenden Samples
aud3len	= $DFF0D4
aud0vol	= $DFF0A8
aud1vol	= $DFF0B8	; Soundregister, enthällt Lautstärke
aud2vol	= $DFF0C8	; der Stimmen
aud3vol	= $DFF0D8
aud0per	= $DFF0A6
aud1per	= $DFF0B6	; Soundregister, enthällt Sampleperiod
aud2per	= $DFF0C6	; 'guasi Tonhöhe' für Paula
aud3per	= $DFF0D6

	; *** Basisadressen ***

exbase= 4		; Exec Basisadresse

; Tabellen, Variablen und Zwischenspeicher, am Ende des Listings

	section	routines,code

; ***********************************************************
; *                                                         *
; *                  B E E T H O V E N                      *
; *                                                         *
; * ROUTINEN zum Initialisieren eines SONGFILES im Speicher *
; *                                                         *
; ***********************************************************
; *                                                         *
; *     Assembler-Source-Listing / Assembler: Devpac II     *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Dies ist die Einsprungstelle zum Initialisieren eines Songfiles

; Beim Einsprung in die Routinen muß in a0 ein Zeiger auf die
; Adresse der Sounddaten stehen und wenn möglich in d0 die Länge
; der Sounddaten

; Wenn Sie mit 'bsr GETSONG' in die Routinen einspringen, werden
; das Songfile und eventuell benötigte Instrumente geladen,
; dann fährt das Programm hinter der aufrufenden Zeile fort.
; Die Routinen liefern in D0 den Wert $0, wenn alles geklappt hat.
; Wenn D0 nach dem Rücksprung den Wert $FFFF enthält, ist etwas
; schiefgegangen.

GETSONG:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	move.l	a0,a5
	move.l	d0,d5
	move.l	exbase,a6
	lea	dosname,a1
	moveq	#0,d0
	jsr	OpenLibrary(a6)	;Dos_Library öffnen
	move.l	d0,dosbase
	beq	loadsongerror
	move.l	a5,a0
	move.l	d5,d0		;Datenlänge = 0 ?
	bne	okilfile
	move.l	#200000,d0	;Dann nehmen wir halt 200000
	bra	okilfile

; ***********************************************************
; *                                                         *
; *                  B E E T H O V E N                      *
; *                                                         *
; * ROUTINEN zum LADEN eines SONGFILES und der INSTRUMENTE  *
; *                                                         *
; ***********************************************************
; *                                                         *
; *    Assembler-Source-Listing / Assembler: Devpac II      *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Dies ist die Einsprungstelle zum Laden eines Songfiles

; Beim Einsprung in die Routinen muß in a0 ein Zeiger auf den
; Filenamen des gewünschten Songs stehen

; Wenn Sie mit 'bsr LOADSONG' in die Routinen einspringen, werden
; das Songfile und die benötigten Instrumente geladen, danach
; fährt das Programm hinter der aufrufenden Zeile fort.
; Wenn Sie mehrere Songs in Ihrem Programm verwenden wollen, sollten
; Sie darauf achten, daß Sie niemals die Routinen LOADSONG zum zweiten
; mal aufrufen, bevor Sie nicht den Song durch Aufruf der entsprechenden
; Routinen ( siehe unten ) korrekt beendet haben.
; Die Routinen liefern in D0 den Wert $0, wenn alles geklappt hat.
; Wenn D0 nach dem Rücksprung den Wert $FFFF enthält, ist etwas
; schiefgegangen.

LOADSONG:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	move.l	a0,filepoint	;Zeiger auf Filenamen retten
	move.l	exbase,a6
	lea	dosname,a1
	moveq	#0,d0
	jsr	OpenLibrary(a6)	;Dos_Library öffnen
	move.l	d0,dosbase
	beq	loadsongerror

; Songfile lesen und Version ermitteln
	clr.b	versionflag	;Liedversion noch nicht bekannt
	move.l	filepoint,a0	;Zeiger auf Filenamen
	move.l  #$10003,d0	;Speichertyp: Chip und Clear
	bsr     loadfile	;File laden
	move.l  d0,memlong	;Länge der Daten sichern
	bne     okilfile	;Länge <> 0 ... alles klar
	bra     loadsongerror	;sonst Error oder kein Speicher
okilfile:
	move.l	a0,membase	;Zeiger auf Datenanfang
	move.l	d0,d5		;Länge der Daten
	move.l	a0,a5		;Adresse der Daten
	move.l	4,a6		; Speicher für Wellenform-
	move.l	#17384,d0
	move.l	#$10003,d1	; Instrumente allozieren
	jsr	AllocMem(a6)
	move.l	d0,megamem
	beq	loadsongerror
	add.l	#16384,d0
	move.l	d0,wavemem
	cmp.l	#'AMMS',8(a5)	;Prüfen, ob es sich um ein
	bne	noammsfile	;Komplettsongfile (d.h. inkl.
	move.b	#255,savesongflag	;der Instrumentendaten) handelt

; Bei Komplettsongfiles Adressen der Instrumente ermitteln
	moveq   #15,d7		;16 Instrumente suchen
inschunkl:
	move.l	a5,a4		;Zeiger auf Datenanfang
	move.l	d5,d0		;Länge der Daten
	lsr.l	#1,d0		;durch 2 teilen
	move.l	#'INSX',d4	;Instrumentenkennung, nach der
	move.b	d7,d4		;zu suchen ist nach d4 und
	add.b	#48,d4		;Nummer des Instruments dazu
lfammsins:
	cmp.l	(a4),d4		;Instrumentenkennung gefunden ?
	beq	fammsins	;yeaahh !
	addq.l	#2,a4		;sonst Adresse um 2 erhöhen
	subq.l	#1,d0		;und Zähler vermindern
	bne	lfammsins	;und weiter geht's
gofammsins:
	dbra	d7,inschunkl	;nächstes Instrument suchen
	bra	gotammsinsts	;und dann unten weiter ...

fammsins:	;Instrument gefunden
	add.l	#62,a4		;Zeiger auf Anfang der IFF-Daten
	lea	inst1mem,a1	;Zeiger auf Tabelle der Adressen
	lea	long1mem,a0	;Zeiger auf Tabelle der Längen
	move.l	d7,d1		;Nummer des Instruments mal 4
	asl.l	#2,d1		;gibt Zeiger auf Tabellenplatz
	move.l	(a4),0(a0,d1)	;Länge der Daten in Tabelle
	move.l	(a4),d3		;Zähler zum suchen (unten)
	subq.l	#4,a4
	move.l	a4,0(a1,d1)	;Adresse der IFF-Daten in Tabelle

; Anfang der Sample-Daten/Body-Chunk ermitteln
	move.l	a4,a2		;Anfangsadresse nach a2
ermammibody:
	addq.l	#2,a2		;Adresse um 2 erhöhen
	cmp.l	#'body',(a2)	;BODY-Chunk gefunden ?
	beq	gotammibody
	cmp.l	#'BODY',(a2)	;BODY-Chunk gefunden ?
	beq	gotammibody
	dbra	d3,ermammibody	;Zähler vermindern und weitersuchen
	bra	gofammsins	;und weiter mit dem nächsten Inst
gotammibody:
	addq.l	#4,a2		;Eigentliche Body-Anfangsadresse
	lea	body1mem,a1	;Zeiger auf Body-Tabelle
	move.l	d7,d0		;Instrumentennummer mal 4
	asl.l	#2,d0		;ertgibt Zeiger auf Position
	move.l	a2,0(a1,d0)	;in der Tabelle
	bra	gofammsins	;und weiter mit dem nächsten Inst

;Ermitteln, ob es sich um ein Beethoven-File handelt/Adressen ermitteln
noammsfile:
	cmp.l	#'AMMD',8(a5)	;Prüfen, ob es sich um ein
	bne	noammdfile	;Beethoven Datenfile handelt
	move.l	#'INMS',d4	;Chunk mit Instrumentennamen
	bsr	getchunk	;suchen und
	move.l	a0,namemem	;Adresse sichern

gotammsinsts:
	move.l	#'WFMS',d4	;Chunk mit Wellenformdaten
	bsr	getchunk	;ermitteln und
	move.l	#'MDLS',d4	;Chunk mit Modulationsdaten
	bsr	getchunk	;ermitteln und
	move.l	a0,modulmem	;Adresse sichern
	move.l	#'SDTA',d4	;Chunk mit Rahmendaten
	bsr	getchunk	;ermitteln
	move.b	(a0),speedwert	;Geschwindigkeit laden
	bset	#1,cialed	;Filter ausschalten
	btst	#1,3(a0)	;Filterstatus ermitteln
	bne	ltoff
	bclr	#1,cialed	;Filter einschalten
ltoff:
	tst.w	8(a0)		;Raw-Cycle-Wert lesen
	beq	norawnr		;wenn 0 dann ignorieren
	move.w	8(a0),rawcycle	;sonst sichern
norawnr:

	;Anfänge der eigentlichen Lieddaten der 4 Stimmen suchen
	move.l	a5,a0		;Zeiger auf Anfang der Daten
	move.l	#5000,d0	;Maximalzähler zum Suchen
lfordchunk:
	cmp.l	#'BODY',(a0)	;BODY-Chunk gefunden ?
	beq	fdchunk		;ja ... also weiter
	addq.l	#2,a0		;nein ... Adresse plus 2
	dbra	d0,lfordchunk	;weitersuchen
	bra	loadsongerror	;kein Body-Chunk => kein Song
fdchunk:
	addq.l	#6,a0		;Zeiger auf Notendaten der
	move.l	a0,voice1mem	;ersten Stimme
	bsr	ermitvoiceend	;Ende der Stimme ermitteln
	move.l	a0,voice2mem	;Zeiger auf Daten der 2.Stimme
	bsr	ermitvoiceend	;Ende der Stimme ermitteln
	move.l	a0,voice3mem	;Zeiger auf Daten der 3.Stimme
	bsr	ermitvoiceend	;Ende der Stimme ermitteln
	move.l	a0,voice4mem		;Zeiger auf Daten der 4.Stimme

	tst.b	savesongflag	;Wenn der Song ein Komplettfile
	bne	loaded		;is, san mer fertig !
	bsr	lookforinsts	;Sonst Instrumente nachladen
	bra	loaded		;und dann san mer fertig !

ermitvoiceend:	;Ende einer Stimme ermitteln
	addq.l	#2,a0		;Adresse plus 2
lookvend:
	move.b	(a0)+,d0	;ein Byte überspringen
	move.b	(a0)+,d0	;zweites Byte = 0 ?
	bne	lookvend	;nein ... weitersuchen
	subq.l	#2,a0		;Adresse minus 2 gibt Anfang
	rts			;fertig !

; Anfang eines Chunks ermitteln
getchunk:			;Anfang eines Chunks ermitteln
	move.l	a5,a0		;Anfangsadresse nach a0
	move.l	#5000,d0	;maximal 10000 Byte durchsuchen
lforlschunk:
	cmp.l	(a0),d4		;Chunkkennung gefunden ?
	beq	flschunk	;ja ... toll ! Chunk gefunden
	addq.l	#2,a0		;Adresse um 2 erhöhen
	dbra	d0,lforlschunk	;und weitersuchen
	rts			;nichts gefunden ! => Fertig
flschunk:
	cmp.l	#"WFMS",d4	;Wellenformchunk gefunden ?
	beq	specialo	;ja ... Spezialbehandlung erforderlich
	move.l  4(a0),d0	;nein ... dann Länge nach d0
	addq.l	#8,a0		;und Anfangsadresse nach a0
	rts			;und fertig
specialo:
	addq.l	#8,a0		;Adresse von Wellenformchunk nach a0
	move.l	#255,d0		;256 Amplitude-Werte kopieren
	move.l	wavemem,a1	;Zeiger auf Wellenformspeicher
coplwmem1:
	move.b	(a0),(a1)+	;Amplitudenwert 
	move.b	(a0)+,(a1)+	;zweimal kopieren
	dbra	d0,coplwmem1	;Kopierschleife
	move.l	#255,d0		;256 Volume-Werte kopieren
	move.l	wavemem,a1	;Zeiger auf Wellenformspeicher
	add.l	#700,a1		;für Volumes
coplwmem2:
	move.b	(a0)+,(a1)+	;Kopierschleife
	dbra	d0,coplwmem2
	rts

; Daten für alte Wizard of Sound - File ermitteln
noammdfile:
	bclr	#1,cialed	;Filter einschalten
	move.l	membase,a1	;Zeiger auf Anfang der Daten
	add.l	#8992,a1	;Abspielgeschwindigkeit
	move.b	(a1)+,speedwert	;ermitteln
	move.b	#2,versionflag	;Version => 2.0
	addq.l	#3,a1		;Prüfen ob Song-Version
	cmp.l	#'WOS2',(a1)	;größer als V1.0
	beq	newwosfile	;JA ! also neues W.O.S.-File
	bsr	oldwosfile	;Nein ! Werte für altes File
	move.b	#1,versionflag	;ermitteln
newwosfile:
	move.l	membase,a1	;Zeiger auf Anfang der Daten
	move.l	a1,voice1mem	;Zeiger auf Daten der 1.Stimme
	add.l	#2000,a1
	move.l	a1,voice2mem	;Zeiger auf Daten der 2.Stimme
	add.l	#2000,a1
	move.l	a1,voice3mem	;Zeiger auf Daten der 3.Stimme
	add.l	#2000,a1
	move.l	a1,voice4mem	;Zeiger auf Daten der 4.Stimme
	add.l	#2100,a1
	move.l	a1,namemem	;Zeiger auf Instrumentennamen
	bsr	lookforinsts	;und Instrumente laden
	bra	loaded		;und fertig !

; Nötige Instrumente ermitteln und laden

lookforinsts:
	moveq	#0,d4
	moveq	#0,d5
	moveq	#15,d6		;16 Instrumente suchen
	lea	long1mem,a5	;Zeiger auf Längentabelle
	lea	instwerttab,a4	;Zeiger auf Instr.-Kennungen
testloop:
	move.b	0(a4,d4),d5	;Instrumentenkennwert lesen
	moveq	#0,d7		;Flag auf unbenutzt setzen
	tst.b	versionflag	;prüfen auf W.O.S.-Song
	bne	noammsis	;ja ... also Unten suchen
	move.l	voice1mem,a1	;Zeiger auf Anfang der 1.Stimme
	move.l	voice1mem,d1
	sub.l	membase,d1	;Länge des zu durchsuchenden
	move.l	memlong,d2
	sub.l	d1,d2		;Bereichs ermitteln
	bra	suchinst	;und Bereich durchsuchen
noammsis:
	move.l	voice1mem,a1	;Zeiger auf Anfang der 1.Stimme
	move.l	#7999,d2	;Länge des Bereichs
suchinst:
	cmp.b	0(a1,d2),d5	;Instrumentenkennung gefunden ?
	beq	instfound	;yeaahhh ! ... Instrument gefunden
	subq.l	#1,d2		;Zähler um eins vermindern
	bne	suchinst	;und weitersuchen
	bra	noinstfound	;Instrument nicht gefunden
instfound:
	move.l	#1,d7		;Instrument gefunden > merken
noinstfound:
	move.l	d7,(a5)		;Merkflag in Längentabelle
	addq.l	#4,a5		;Zeiger in Tabelle erhöhen
	addq.b	#1,d4		;Zeiger in Kennwerttabelle erhöhen
	dbra	d6,testloop	;nächstes Instrument suchen

; Instrument_Directory im Aktuellen Directory suchen
	move.l	dosbase,a6
	move.l	#instdir,d1	;Lock des Instrumenten-
	move.l	#-2,d2		;Verzeichnisses ermitteln
	jsr	Lock(a6)
	move.l	d0,instlock
	beq	loadsongerror
	move.l	d0,d1
	jsr	CurrentDir(a6)	;Instr.Dir wird actual_dir
	move.l	d0,oldlock	;altes Dir-Lock sichern

;benötigte Instrumente laden
	moveq	#15,d6		;Zähler für 16 Instrumente
	moveq	#0,d7
	move.l	namemem,a4	;Zeiger auf Inst-Namentabelle
	lea	long1mem,a3	;Zeiger auf Längentabelle
	lea	inst1mem,a2	;Zeiger auf Adressentabelle
	lea	body1mem,a1	;Zeiger auf Bodytabelle
getisloop:
	move.l	d7,d3		;Zeiger auf Position in der
	asl.l	#2,d3		;Längentabelle ermitteln
	tst.l	0(a3,d3)	;und prüfen, ob Instrument
	beq	nextgeti	;gebrauch wird ...
	move.l	a4,a0		;Zeiger auf Instrumentennamen
	move.l	#$10003,d0	;Speichertyp: Chip und Clear
	bsr	loadfile	;File laden
	move.l	a0,0(a2,d3)	;Zeiger auf Adresse sichern
	move.l	d0,0(a3,d3)	;Länge des Files sichern
	beq	loadsongerror	;Instrument nicht gefunden => Error

; Anfang des Body-Chunks ermitteln
	move.l	d0,d5		;Maximalzähler zum Ermitteln
	lsr.l	#1,d5
ermgibody:
	cmpi.l	#"BODY",(a0)	;auf 'BODY'-Kennung prüfen
	beq	gotibody	;ja ... super !
	addq.l	#2,a0		;Adresse plus 2
	dbra	d5,ermgibody	;und weitersuchen
; Wenn's kein IFF-8SVX-File ware nehmen wir's als Raw-Sample
gotrawsample:
	move.l	0(a3,d3),d0	;Länge der Daten
	add.l	#50,d0		;plus 50 für den Kopf
	move.l	#$10003,d1	;und nochmal
	move.l	4,a6
	jsr	AllocMem(a6)	;Speicher allozieren
	tst.l	d0
	beq	loadsongerror	;kein Speicher ?!?!!?!?
	move.l	d0,d5		;Zeiger auf neuen Speicher sichern
	moveq	#47,d1
	move.l	d0,a1		;IFF-SMUS-Kopf
	lea	rawhead,a0
copyrawhead:
	move.b	(a0)+,(a1)+	;vor Raw-Daten kopieren
	dbra	d1,copyrawhead
	move.l	d5,a1
	move.l	0(a3,d3),d0	;Daten in SMUS-Kopf
	move.l	d0,4(a1)
	add.l	#32,4(a1)
	move.l	d0,20(a1)	;schreiben
	move.l	d0,44(a1)
	move.l	#"RAWI",28(a1)
	move.l	0(a2,d3),a0	;und
	move.l	d5,a1
	adda.l	#48,a1		;schließlich
copyrawdata:
	move.b	(a0)+,(a1)+	;eigentliche Sample-Daten
	subq.l	#1,d0	
	bne	copyrawdata	;kopieren
	move.l  0(a2,d3),a1
	move.l  0(a3,d3),d0
	jsr	FreeMem(a6)	;alten Speicher freigeben
	move.l	d5,0(a2,d3)
	add.l	#50,0(a3,d3)	;und neue Adresse und
	move.l	d5,a0
	adda.l	#40,a0		;Länge sichern
gotibody:
	addq.l	#4,a0		;Zeiger auf eigentlichen Anfang
	lea	body1mem,a1	;Zeiger auf Bodytabelle
	move.l	a0,0(a1,d3)	;der Body-Daten sichern
nextgeti:
	adda.l	#50,a4		;Zeiger auf nächsten Inst-Namen
	addq.b	#1,d7		;Nummer des Instruments plus 1
	dbra	d6,getisloop	;und weiter geht's
	bra	loaded		;und fertig !

; Song von alter W.O.S.-Version/Instrumentennamen konvertieren
oldwosfile:
	move.l	exbase,a6	;Zwischenspeicher zum
	move.l	#400,d0		;Konvertieren der Instrumenten-
	moveq	#$1,d1		;Tabelle anfordern
	jsr	AllocMem(a6)
	move.l	d0,a1		;Huch ! kein Speicher
	beq	loadsongerror	;Pech gehabt !
	move.l	d0,a3		;Zeiger auf Zwischenspeicher
	move.l	membase,a5	;Zeiger auf Anfang der Instr-
	add.l	#8100,a5	;Tabelle in einem alten W.O.S.-
	moveq	#49,d0		;File
olwol1:
	move.b	0(a5),0(a3)	;Namen der Instrumente auf das
	move.b	100(a5),50(a3)
	move.b	200(a5),100(a3)	;Format in neuen W.O.S.-Files
	move.b	300(a5),150(a3)
	move.b	50(a5),200(a3)	;umkopieren
	move.b	150(a5),250(a3)
	move.b	250(a5),300(a3)
	move.b	350(a5),350(a3)
	addq.l	#1,a5
	addq.l	#1,a3
	dbra	d0,olwol1
	move.l	a1,a3		;Zeiger auf Zwischenspeicher
	move.l	membase,a5	;und auf Instrumententabelle
	add.l	#8100,a5	;für neue W.O.S.-Files
	move.l	#399,d0
olwol2:				;Zwischenspeicher als neue
	move.b	(a3)+,(a5)+	;Instrumententabelle
	dbra	d0,olwol2	;zurück kopieren
	move.l	#400,d0		;und Zwischenspeicher wieder
	jsr	FreeMem(a6)	;freigeben
	rts

; *** Wellenformen zu Instrumenten aufarbeiten ***

aufarbeit:
	moveq	#7,d7		;7 Wellenformen zum Aufarbeiten
aufarl2:
	move.l	d7,d0		;Nummer der Wellenform
	asl.w	#8,d0		;mal 2048
	asl.w	#3,d0
	move.l	megamem,a0	;Zeiger auf Speicher Instrumentenform
	add.l	d0,a0		;berechnen
	move.l	wavemem,a1
	move.l	d7,d1		;Zeiger auf Wellenformspeicher
	asl.w	#6,d1		;der Amplitude berechnen
	add.l	d1,a1
	moveq	#63,d6		;Wellenform 64mal berechnen
aufarl3:
	move.l	wavemem,a2
	add.l	#700,a2		;Zeiger auf Wellenformspeicher
	move.l	d7,d2		;berechnen
	asl.w	#5,d2
	add.l	d2,a2
	moveq	#0,d0		;Instrument aus
	move.b	(a1)+,d0
	moveq	#31,d5		;Wellenformdaten
aufarl4:
	moveq	#0,d1
	move.b	(a2)+,d1	;berechnen
	mulu	d0,d1
	divu	#127,d1
	move.b	d1,(a0)+
	dbra	d5,aufarl4
	dbra	d6,aufarl3
	dbra	d7,aufarl2
	rts

; Loadfile-Routine, ermittelt die Länge eines Files und läd es 

loadfile:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	move.l	a0,a5		;Zeiger auf Namen retten
	move.l	d0,d5		;Mem-Type retten
	move.l	dosbase,a6	;Dos-Basisadresse in a6
	move.l	a5,d1		;Zeiger auf Namen in d1
	moveq	#-2,d2		;Lock-Mode = -2 ... Lesen !
	jsr	Lock(a6)	;Filelock ermitteln
	move.l	d0,d7		;Zeiger auf Filelock in d7
	beq	lerror1		;Zeiger = 0 ... Error !
	move.l	exbase,a6
	move.l	#300,d0		;Zwischenspeicher für Info-
	move.l	#$10003,d1	;Data des Files allozieren
	jsr	AllocMem(a6)
	move.l	d0,d6
	beq	lerror1		;kein Speicher => kein File
	move.l	dosbase,a6
	move.l	d7,d1		;Zeiger auf Filelock in d1
	move.l	d6,d2		;Zeiger auf Fileinfospeicher
	move.l	d2,a3
	jsr	Examine(a6)	;Fileinfodaten lesen
	tst.l	d0		;d0 = 0 ? ... Error !
	beq	lerror1
	move.l	d7,d1		;Zeiger auf Filelock in d1
	jsr	UnLock(a6)	;Filelock wieder freigeben
	move.l	124(a3),d0	;Länge des Files lesen
	addq.l	#4,d0		;plus 4 Byte für diesen Fall !
	move.l	exbase,a6	;Exec-Basisadresse in a6
	move.l	d5,d1		;Mem-Type nach d1
	jsr	AllocMem(a6)	;Speicher allocieren
	move.l	d0,a2		;Zeiger auf Speicher retten
	beq	lerror1		;Zeiger = 0 ? ... Error !
	move.l	a5,d1		;Zeiger auf Filenamen in d1
	move.l	#1005,d2	;Open-Mode: Mode_old ('altes File')
	move.l	dosbase,a6	;Dos-Basisadresse in a6
	jsr	Open(a6)	;File öffnen
	move.l	d0,d4		;Filehandle retten
	beq	lerror1		;Filehandle = 0 ? ... Error !
	move.l	d0,d1		;Filehandle in d1
	move.l	a2,d2		;Zeiger auf Speicher in d2
	move.l	124(a3),d3	;Länge des Files in d3
	jsr	Read(a6)	;Fileinhalt lesen
	move.l	d4,d1		;Filehandle in d1
	jsr	Close(a6)	;File schließen
	move.l	124(a3),d4	;Länge des Files in d4
	addq.l	#4,d4
	move.l	exbase,a6	;Speicher für Fileinfodaten
	move.l	d6,a1		;wieder freigeben
	move.l	#300,d0
	jsr	FreeMem(a6)
	move.l	a2,a0		;Zeiger auf Speicher in a0
	move.l	d4,d0		;Länge des Speicherblock in d0
exitloadfile:
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	rts			;und Fertig !
lerror1:
	moveq	#0,d0		;d0 = 0 ... Error !
	bra	exitloadfile	;und Fertig !

; *** Alles ist geladen ... also weiter geht's ***

loaded:
	move.l	dosbase,a6
	tst.b	savesongflag	;Unten weiter, wenn es sich um
	bne	noidir		;einen Komplettsong handelte
	move.l	oldlock,d1	;oder hier altes (CLI-)Dir
	beq	doclidir
	jsr	CurrentDir(a6)	;zum actual_dir machen
doclidir:
	move.l	instlock,d1	;Inst-Dir-Lock freigeben
	beq	noidir
	jsr	UnLock(a6)
noidir:
	moveq	#0,d0
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	rts

; *** Etwas ist schief gegangen ... au Weia ! ***

loadsongerror:
	jsr	DROPSONG
	move.l	#$FFFF,d0
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	rts



; ***********************************************************
; *                                                         *
; *                  B E E T H O V E N                      *
; *                                                         *
; *             ROUTINEN zum STARTEN der MUSIK              *
; *                                                         *
; ***********************************************************
; *                                                         *
; *    Assembler-Source-Listing / Assembler: Devpac II      *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Wenn Sie nachfolgende Routinen mit 'bsr STARTMUSIK' aufrufen,
; werden die Interruptroutinen zum Abspielen des Songs initialisert
; und das Abspiel des Songs beginnt. Danach springt das Programm
; hinter die Aufrufstelle zurück und Sie können Ihr eigenes Programm
; fortsetzen, während im Hintergrund die Musik gespielt wird.
; Die Musik wird in einer Endlosschleife gespielt, bis sie die Routinen
; zum Stoppen der Musik aufrufen.
; Wenn Sie mehrere verschiendene Songs in Ihrem Programm abspielen
; wollen, sollten Sie darauf achten, daß Sie niemals die Routinen
; STARTMUSIK nochmals aufrufen, bevor Sie nicht den alten Song
; beendet und einen neuen geladen haben.

; Instrument für den Start suchen, falls keins gesetzt ist

STARTMUSIK:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	move.l	voice1mem,a0	;Zeiger auf Anfang Stimme 1
	bsr	prüfiprüfi	;Prüfen ob Instrument gesetzt
	bsr	dowhatinst	;Werte für Instrument ermitteln
	move.l	d2,instvoice1	;und für Stimme 1
	move.l	d3,bodyvoice1	;setzen
	move.l	voice2mem,a0
	bsr	prüfiprüfi	;selbiges für Stimme 2
	bsr	dowhatinst
	move.l	d2,instvoice2
	move.l	d3,bodyvoice2
	move.l	voice3mem,a0
	bsr	prüfiprüfi	;analog für Stimme 3
	bsr	dowhatinst
	move.l	d2,instvoice3
	move.l	d3,bodyvoice3
	move.l	voice4mem,a0
	bsr	prüfiprüfi	;und Stimme 4
	bsr	dowhatinst
	move.l	d2,instvoice4
	move.l	d3,bodyvoice4
	bra	goforplay	;jetzt geht's zum Abspielen

prüfiprüfi:
	moveq	#0,d1
	cmp.b	#220,3(a0)	;Prüfen, ob an der ersten
	bls	nowwelinst
	cmp.b	#229,3(a0)	;Position in der Stimme ein
	beq	nowwelinst
	cmp.b	#230,3(a0)	;Instrumentenaufruf steht ?
	beq	nowwelinst
	cmp.b	#238,3(a0)      
	bls	securi
	bra	nowwelinst	;kein Aufruf gefunden ...
securi:
	move.b	3(a0),d1	;Instrument gefunden
	rts
nowwelinst:			;Ersatzinstrument ermitteln
	lea	long1mem,a5	;Zeiger auf Instrument 1
	moveq	#15,d4		;maximal 16 mal suchen
	moveq	#0,d5
weliloop:
	move.l	0(a5,d5),d0	;Prüfen ob das Instrument
	bne	gotweli		;besetzt ist ...
	addq.l	#4,d5		;wenn nicht, dann nächstes
	dbra	d4,weliloop	;prüfen
gotweli:
	tst.l	d5
	beq	nullweli
	lsr.l	#2,d5		;Instrumentennummer ermitteln
nullweli:
	lea	instwerttab,a5	;und Instrumentenkennung lesen
	move.b	0(a5,d5),d1
	rts			;zurück zum Setzen des Instr.

; *** Weiter geht's mit dem Start des Abspiels ***

goforplay:
	bsr	aufarbeit
	clr.w	point1
	clr.w	point2		;Zeiger auf Noten für Start
	clr.w	point3
	clr.w	point4
	move.b	speedwert,speedplay	;Geschwindigkeit
	clr.l	cres1
	clr.l	decr1		;alle übrigen Zeiger löschen
	clr.l	repc1
	clr.l	triolecount1
	clr.l	duolecount1
	clr.l	bogenflag1
	clr.l	volmod1
	clr.l	freqmod1
	move.l	#$ffffffff,paused1
	clr.w	triolerest1
	clr.w	triolerest2
	clr.w	triolerest3
	clr.w	triolerest4
	move.w	#5,long1
	move.w	#5,long2	;noch 1/10 Sekunge, dann
	move.w	#5,long3
	move.w	#5,long4	;geht's los
	move.w	#40,vol1
	move.w	#40,vol2	;Anfangslautstärke
	move.w	#40,vol3
	move.w	#40,vol4	;Mezzoforte
	move.w	#15,dmacon	;DMA erst noch aus !

; Abspielroutinen in den Vertical_Blanking_Interrupt

	move.l	exbase,a6
	lea	irqmem,a1	;Speicher für Interruptstruktur
	move.l	a1,d0
	add.l	#32,d0		;Werte für Interrupt-Server
	move.l	d0,14(a1)
	move.b	#-32,9(a1)	;initialisieren
	move.b	#2,8(a1)
	lea	voice1,a2	;näheres siehe z.Bsp.
	move.l	a2,18(a1)	;Amiga Intern von DB
	moveq	#5,d0
	jsr	AddIntServer(a6)	;Interrupt-Server einhängen

	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	moveq	#0,d0
	rts


; ***********************************************************
; *                                                         *
; *                  B E E T H O V E N                      *
; *                                                         *
; *             ROUTINE zum STOPPEN der MUSIK               *
; *                                                         *
; ***********************************************************
; *                                                         *
; *   Assembler-Source-Listing / Assembler: Devpac II       *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Wenn Sie das Abspiel der Musik beenden wollen rufen Sie folgende
; Routine mit 'bsr STOPMUSIK' auf.
; Achtung: Rufen sie STOPMUSIK nur auf, wenn Sie vorher auch
; STARTMUSIK aufgerufen hatten.

STOPMUSIK:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	lea	irqmem,a1
	moveq	#5,d0
	move.l	exbase,a6	;Interrupt aus Liste entfernen
	jsr	RemIntServer(a6)
	move.w	#15,dmacon	;Audio-DMA ausschalten
	move.w	#0,aud0vol
	move.w	#0,aud1vol
	move.w	#0,aud2vol
	move.w	#0,aud3vol
	moveq	#0,d0
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	rts


; ***********************************************************
; *                                                         *
; *                  B E E T H O V E N                      *
; *                                                         *
; *           ROUTINE zum FREIGEBEN des SPEICHERS           *
; *                                                         *
; ***********************************************************
; *                                                         *
; *   Assembler-Source-Listing / Assembler: Devpac II       *
; *                                                         *
; *                   (C)Oktober 1990 by                    *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Folgende Routine gibt sämtliche Speicherbereiche wieder frei.
; Die Routine rufen Sie mit 'bsr DROPSONG' auf.
; Achten Sie darauf, daß sich überhaupt ein Song im Speicher
; befindet und daß die Musik abgeschaltet ist, bevor Sie DROPSONG
; aufrufen.

DROPSONG:
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	bsr	cliralli	;Instrumentenspeicher freigeben
	move.l	exbase,a6
	move.l	membase,a1	;Lieddatenspeicher freigeben
	move.l	memlong,d0
	beq	nomemtclr
	jsr	FreeMem(a6)
nomemtclr:
	tst.l	megamem
	beq	nomegaclear	;Speicher für Wellenform-
	move.l	megamem,a1
	move.l	#17384,d0
	jsr	FreeMem(a6)	;instrumente freigeben
	clr.l	megamem
nomegaclear:
	move.l	dosbase,a1
	jsr	CloseLibrary(a6)	;Dos-Lib schließen
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückhohlen
	rts			;und Ende

; *** Speicher für Instrumente freigeben ***

cliralli:
	tst.b	savesongflag	;Prüfen, ob Komplettsong geladen
	bne	exitcliri	;dann gibt's keine Inst-Freigabe
	move.l	4,a6
	lea	long1mem,a5	;Zeiger auf Längentabelle
	lea	inst1mem,a4	;Zeiger auf Adressentabelle
	moveq	#15,d4		;max. 16 Instrumente löschen
	moveq	#0,d5
clraliloop:
	move.l	0(a5,d5),d0	;Länge lesen, wenn = 0 ?
	beq	nextcliralli	;kein Instrument ... also nächstes
	cmp.l	#1,d0
	beq	nextcliralli
	move.l	0(a4,d5),a1	;Zeiger auf Adresse
	jsr	FreeMem(a6)	;Speicher freigeben
	clr.l	0(a5,d5)	;und Zeiger für Länge
	clr.l	0(a4,d5)	;und Adresszeiger löschen
nextcliralli:
	clr.l	0(a5,d5)	;und Zeiger für Länge
	clr.l	0(a4,d5)	;und Adresszeiger löschen
	addq.l	#4,d5		;Zeiger auf nächstes Instrument
	dbra	d4,clraliloop	;und weiter geht's
exitcliri:
	rts


; ***********************************************************
; *                                                         *
; *        A M I G A  M U S I C  M O N S T E R  V 2.5       *
; *                                                         *
; *                      ABSPIELROUTINEN                    *
; *                                                         *
; ***********************************************************
; *                                                         *
; *                 Assembler-Source-Listing                *
; *                                                         *
; *                    (C)April 1990 by                     *
; *                                                         *
; *                   Dan Dark  Software                    *
; *                     Jörg Schließer                      *
; *                   Hasenbergsteige 15                    *
; *                    7000 Stuttgart 1                     *
; *                      West-Germany                       *
; *                                                         *
; ***********************************************************

; Folgende Routinen lauf im Vertical_Blanking_Interrupt

voice1:				;Routinen für Stimme 1
	movem.l	d1-d7/a1-a6,-(sp)	;Registerinhalte retten
	tst.w	stlong1		;Prüfen, ob Staccatozähler
	beq	nosslo1		;ungleich 0
	subq.w	#1,stlong1	;ja ... runterzählen
nosslo1:
	bsr	modvolume1	;Lautstärkemodulation
	bsr	modfrequenz1	;Frequenzmodulation
	subq.w	#1,long1	;Längenzähler um 1 vermindern
	beq	dovoice1	;wenn null, dann nächste Note
	cmp.w	#1,long1	;Längenzähler = 1 ?
	bne	voice2		;nein ... also weiter mit Stimme 2
	moveq	#0,d0		;Wenn Längenzähler = 1 dann
	move.w	point1,d0	;aktuelle Positionsnummer in d0
	asl.w	#1,d0		;ergibt Zeiger auf Position
	move.l	voice1mem,a0
	cmp.b	#219,3(a0,d0)	;Prüfen auf Haltebögen ( oben
	beq	voice2		;und unten ), wenn ja dann
	cmp.b	#218,3(a0,d0)	;weiter mit Stimme 2
	beq	voice2
	move.w	#0,aud0vol	;sonst Stimme 1 ausschalten
	move.w	#1,dmacon
	bra	voice2		;und weiter mit Stimme 2
dovoice1:
	cmp.b	#1,triolecount1	;Prüfen, ob Restwartezeit
	bne	norestwart1	;von Triole zu spielen ist
	move.w	triolerest1,long1	;wenn ja, Rest in Triolenzähler
	beq	norestwart1	;Rest = 0 ? ... weiter unten
	clr.w	triolerest1
	clr.b	triolecount1	;sonst Restzeiger löschen und
	bra	voice2		;weiter mit Stimme 2
norestwart1:
	addq.w	#1,point1	;Notenzeiger um 1 erhöhen
	moveq	#0,d0
	moveq	#0,d1
	move.w	point1,d0	;Notenzeiger nach d0
	asl.w	#1,d0		;und Zeiger auf Position ermitteln
	move.l	voice1mem,a0	;Zeiger Notendaten für 1. Stimme
	move.b	1(a0,d0),d1	;Notenlänge lesen, wenn Länge <> 0
	bne	noendsong1	;dann Ende der Stimme nicht erreicht
	clr.b	repc1
	move.w	#1,point1	;sonst Zeiger auf Anfang setzen
	moveq	#2,d0
	move.b	1(a0,d0),d1	;und erste Notenlänge lesen
	beq	voice2		;wieder 0 ? ... Leere Stimme
noendsong1:
	cmp.b	#255,d1		;Notenzeichen = Taktstrich ?
	beq	dovoice1
	cmp.b	#254,d1		;wenn ja, nächstes Zeichen lesen
	beq	dovoice1
	cmp.b	#191,d1
	beq	dovoice1	;Notenzeichen = Formatzeichen
	cmp.b	#190,d1
	beq	dovoice1	;für Ausdruck ?
	cmp.b	#189,d1
	beq	dovoice1	;wenn ja, nächstes Zeichen lesen
	tst.b	d1		;Zeichenwert < 128, dann gleich
	bpl	noszeich1	;zu Pause, bzw. Note verzweigen
	bsr	dowhatwelle	;Prüfen, ob Wellenform als
	cmp.b	#9,d2
	beq	nowellset1	;Instrument gewünscht ist
	move.b	d2,doshortinst1
	bra	dovoice1	;dann weiter mit nächstem Zeichen
nowellset1:
	bsr	dowhatvmod	;Prüfen, ob Aufruf für
	cmp.b	#9,d2
	beq	novolmodset1	;Lautstärkemodulation gewünscht
	move.b	d2,volmod1
	bra	dovoice1	;ist
novolmodset1:
	bsr	dowhatfmod	;Prüfen, ob Aufruf für
	cmp.b	#9,d2
	beq	nofreqmodset1	;Frequenzmodulation gewünscht
	move.b	d2,freqmod1
	bra	dovoice1	;ist
nofreqmodset1:
	bsr	dowhatinst	;Prüfen auf Instrumentenaufruf
	tst.l	d2
	beq	noinstsetv1	;kein Aufruf ... unten weiter
	clr.b	doshortinst1
	move.l	d2,instvoice1	;sonst Werte für neues Inst setzen
	move.l	d3,bodyvoice1
	bra	dovoice1	;und nächstes Zeichen lesen
noinstsetv1:
	cmp.b	#217,d1		;Zeichen = Staccatostart ?
	bne	nostonpl1	;wenn nein ... unten weiter
	move.b	#1,stackato1	;Staccato für Stimme 1 ein
	bra	dovoice1	;und nächstes Zeichen
nostonpl1:
	cmp.b	#216,d1		;Zeichen = Staccatostop ?
	bne	nostoffpl1	;wenn nein ... unten weiter
	clr.b	stackato1	;Staccato für Stimme 1 aus
	bra	dovoice1	;nächstes Zeichen
nostoffpl1:
	cmp.b	#230,d1		;Notenzeichen = Wiederholungsanfang ?
	bne	norepstapl1	;wenn nein ... unten weiter
	cmp.b	#19,repc1	;Schachteltiefe der Wiederholungen
	beq	dovoice1	;schon 19 ? ... nichts geht mehr !
	addq.b	#1,repc1	;Tiefenzähler um 1 erhöhen
	move.b	repc1,d1
	asl.b	#1,d1		;und aktuelle Notenposition in der
	lea	reps1,a0
	move.w	point1,0(a0,d1)	;Wiederholungstabelle ablegen
	bra	dovoice1
norepstapl1:
	cmp.b	#229,d1		;Notenzeichen = Wiederholungsende ?
	bne	norependpl1	;wenn nein ... unten weiter
	move.b	repc1,d1
	asl.b	#1,d1		;Notenposition aus der Tabelle lesen
	lea	reps1,a0
	move.w	point1,d0	;und mit aktueller Position vergl.
	cmp.w	(a0,d1),d0
	bne	wieder1		;wenn ungleich, dann Wiederholung
	clr.w	0(a0,d1)
	cmp.b	#0,repc1	;sonst: Widerholung beendet
	beq	dovoice1	;Zähler schon 0 ? ... nächste Note
	sub.b	#1,repc1	;sonst Zähler vermindern
	bra	dovoice1	;und nächste Note
wieder1:
	move.w	(a0,d1),point1	;Aktuelle Position als Wieder-
	move.w	d0,(a0,d1)	;holungsende in der Tabelle sichern
	bra	dovoice1	;und nächste Note
norependpl1:
	cmp.b	#240,d1		;Notenzeichen = Fermate ?
	bne	nofermate1	;nein ... unten weiter
	move.b	#255,fermateflag	;ja... Flag für Fermate setzen
	bra	dovoice1	;nächste Note
nofermate1:
	cmp.b	#253,d1		;Notenzeichen = Ritardando ?
	bne	noritar1	;nein ... unten weiter
	cmp.b	#7,speedplay	;Geschwindigkeit schon minimal ?
	beq	dovoice1	;wenn ja: nächste Note
	addq.b	#1,speedplay	;sonst Geschwindigkeit vermindern
	bra	dovoice1	;und weiter mit nächster Note
noritar1:
	cmp.b	#252,d1		;Notenzeichen = Accelerando ?
	bne	noaccel1	;nein ... unten weiter
	tst.b	speedplay	;Geschwindigkeit schon maximal ?
	beq	dovoice1	;wenn ja: nächste Note
	subq.b	#1,speedplay	;sonst Geschwindigkeit erhöhen
	bra	dovoice1	;und nächste Note
noaccel1:
	bsr	dowhatlaut	;Prüfen ob neue Lautstärke
	tst.w	d2		;gefragt ist
	beq	nonewlaut1	;nein ! also weiter
	move.w	d2,vol1		;ja ! also neue Lautstärke
	bra	dovoice1	;nächste Note
nonewlaut1:
	cmp.b	#247,d1		;Notenzeichen = Crescendo ?
	bne	nocrescendo1	;nein ... unten weiter
	clr.b	decr1		;sonst Decrescendo löschen
	move.b	#4,cres1	;und Crescendozähler setzen
	bra	dovoice1	;nächste Note
nocrescendo1:
	cmp.b	#248,d1		;Notenzeichen = Decrescendo ?
	bne	nodecrescendo1	;nein ... unten weiter
	clr.b	cres1		;sonst Crescendo löschen
	move.b	#4,decr1	;und Decrescendozähler setzen
	bra	dovoice1	;nächste Note
nodecrescendo1:
	cmp.b	#239,d1		;Notenzeichen = Triole ?
	bne	notriolst1	;nein ... unten weiter
	move.b	#4,triolecount1	;Triolenzähler setzen
	bra	dovoice1	;und weiter
notriolst1:
	cmp.b	#220,d1		;Notenzeichen = Duole ?
	bne	noduolst1	;nein ...
	move.b	#2,duolecount1	;Duolenzähler setzen
	bra	dovoice1	;...
noduolst1:
	cmp.b	#219,d1		;Notenzeichen = Bogen oben ?
	bne	nobho1		;nein...
	move.b	#255,bogenflag1	;Flag für Haltebogen setzen
	move.b	high1,d1	;Prüfen, ob gleiche Notenhöhe
	cmp.b	2(a0,d0),d1	;bei der nächsten Note
	beq	dovoice1	;ja ... also gleich weiter
	move.w	#1,dmacon	;nein ... Stimme kurz ausschalten
	bra	dovoice1	;weiter ...
nobho1:
	cmp.b	#218,d1		;Notenzeichen = Bogen unten ?
	bne	nobti1		;nein ...
	move.b	#255,bogenflag1	;Flag für Haltebogen setzen
	move.b	high1,d1	;Prüfen, ob gleiche Notenhöhe
	cmp.b	2(a0,d0),d1	;bei der nächsten Note
	beq	dovoice1	;ja ... gleich weiter
	move.w	#1,dmacon	;nein ... Stimme kurz ausschalten
	bra	dovoice1	;weiter...
nobti1:
noszeich1:
	tst.b	cres1		;Crescendo aktiv ?
	beq	nodocres1	;nein... unten weiter
	subq.b	#1,cres1	;sonst Zähler vermindern
	cmp.w	#64,vol1	;Lautstärke schon maximal ?
	bge	nodocres1	;ja ... weiter
	addq.w	#4,vol1		;nein ... Lautstärke erhöhen
nodocres1:
	tst.b	decr1		;Decrescendo aktiv ?
	beq	nododecr1	;nein ... weiter
	subq.b  #1,decr1	;Zähler verminder
	cmp.w	#0,vol1		;Lautstärke schon minimal ?
	bls	nododecr1	;ja ... unten weiter
	subq.w	#4,vol1		;Lautstärke vermindern
nododecr1:
	asl.w	#1,d1		;kein Sonderzeichen, also Notenlänge
	lea	longtab,a1
	move.w  0(a1,d1),d2	;aus der Längentabelle lesen
	moveq	#0,d7
	move.b	speedplay,d7	;und mit Geschwindigkeitswert
	addq.b	#1,d7
	mulu	d7,d2		;multiplizieren
	tst.b	fermateflag	;prüfen, ob Fermate zu spielen
	beq	nodoferm1	;nein ... unten weiter
	asl.w	#1,d2		;sonst Länge mal 2
	clr.b	fermateflag	;und Flag löschen
nodoferm1:
	tst.b	duolecount1	;prüfen, ob Duole zu spielen
	beq	noduopl1	;nein ... unten weiter
	subq.b	#1,duolecount1	;sonst Zähler vermindern
	move.l	d2,d7
	add.w	d7,d2		;und Notenlänge mit 1,5
	add.w	d7,d2
	lsr.w	#1,d2		;multiplizieren
noduopl1:
	cmp.b	#1,triolecount1	;prüfen, ob Triole zu spielen
	bls	nodotriole1	;nein ... unten weiter
	subq.b	#1,triolecount1	;sonst Zähler vermindern
	asl.w	#1,d2		;und Notenlänge mit 2/3
	divu	#3,d2		;multiplizieren
	swap	d2
	move.w	d2,triolerest1	;und den Rest sichern
	swap	d2
nodotriole1:
	move.w	d2,long1	;Notenlänge sichern
	lsr.w	#1,d2		;durch 2 Teilen und in
	move.w	d2,stlong1	;Staccatozähler schreiben
	moveq	#0,d1
	move.b	0(a0,d0),d1	;Notenhöhe lesen und wenn Höhe=0
	bne	isnote1
	move.b	#1,paused1	;dann is es ne' Pause
	bra	voice2
isnote1:
	clr.b   paused1		;es ist keine Pause !
	move.b	d1,high1	;Notenhöhe sichern
	moveq	#0,d4
	move.l	d1,d3		;Oktave der zu spielenden
	divu	#12,d3		;Note ermiteln
	add.w	d3,d4
	addq.b	#1,d4
	move.l	d4,okt1		;und sichern
	move.l	d4,allokt
	tst.b	doshortinst1	;Prüfen, ob Wellenform zu
	beq	noshortplay1	;spielen
	moveq	#0,d0
	move.b	doshortinst1,d0	;Nummer der Wellenform holen
	subq.b	#1,d0
	asl.w	#8,d0
	asl.w	#3,d0		;und Zeiger auf
	move.l	megamem,a0
	adda.l	d0,a0		;Sounddaten ermitteln
	move.l	a0,aud0lch	;und in Chip-Register schreiben
	move.w	#1024,aud0len	;Länge in Chip-Register
	move.l	#3579546,d0
	asl.w	#1,d1		;Abspielperiod für die
	lea	periodtab,a1
	move.w	0(a1,d1),d1	;gewünschte Note ermitteln
	asl.w	#4,d1
	divu	d1,d0
	move.w	d0,aud0per	;und in Chip-Register schreiben
	move.w	d0,period1
	clr.l	okt1
	bra	goshot1		;und weiter geht's unten
noshortplay1:
	move.l	bodyvoice1,d4	;Zeiger auf Bodychunk
	move.l	instvoice1,a3	;und auf Speicher der Stimme
	bsr	ermnotes	;Werte für Chip ermitteln
	move.l	d4,aud0lch	;Adresse der Sounddaten in Chip
	move.w	d7,aud0len	;Samplelänge in Chipregister
	move.w	d0,aud0per	;und Sampleperiod und
	move.w	d0,period1
	move.l	20(a3),d3	;prüfen ob OneShotPart vorhanden
	bne	oneshot1	;ja ... weiter unten
	bsr	longpart1	;nein... Daten für Longpart ermitteln
oneshot1:
	tst.b	bogenflag1	;Prüfen, ob Haltebogen zu spielen
	beq	goshot1		;nein ... also Oneshotpart spieln
	clr.b	bogenflag1	;sonst Flag löschen und
	bsr	longpart1
	tst.l	24(a3)
	beq	dropshot1	;Oneshotpart überspringen
goshot1:
	move.w	#$8201,dmacon	;Audio DMA einschalten
	move.w	vol1,aud0vol	;Lautstärke setzen
dropshot1:
	clr.b	freqcount1	;Zähler für Frequenz- und
	clr.b	volmcount1	;Lautstärkemodulation löschen
	moveq	#70,d0
	divu	long1,d0	;Entsprechend der alktuellen
	move.b	d0,modvoladd1	;Notenlänge Add-Wert für
	move.b	d0,modfreqadd1	;Modulationen errechnen
	bne	noadd1volm
	move.b	#255,modvoladd1	;Bei zu langer Note erfolgt
	move.b	#255,modfreqadd1	;'Spezialbehandlung'
noadd1volm:
	bsr	modvolume1	;Lautstäkemodulation
	move.l	24(a3),d3	;Prüfen, ob Longpart vorhanden
	bne	voice2		;ja ... also weiter mit Stimme 2
	move.l	#10,okt1	;nein ... entsprechendes Flag

voice2:
	tst.b	stackato1	;Prüfen ob Staccato in Stimme 1
	beq	vvoice2		;aktiv ? nein ... weiter unten
	tst.w	stlong1		;Prüfen ob Staccatozähler = 0
	bne	vvoice2		;nein ... weiter unten
	move.w	#0,aud0vol	;ja ... Stimme ausschalten
vvoice2:
	tst.w	stlong2		;sonst alles wie bei Stimme 1 ...
	beq	nosslo2
	subq.w	#1,stlong2
nosslo2:			;siehe oben
	bsr	modvolume2
	bsr	modfrequenz2
	subq.w	#1,long2
	beq	dovoice2
	cmp.w	#1,long2
	bne	voice3
	moveq	#0,d0
	move.w	point2,d0
	asl.w	#1,d0
	move.l	voice2mem,a0
	cmp.b	#219,3(a0,d0)
	beq	voice3
	cmp.b	#218,3(a0,d0)
	beq	voice3
	move.w	#0,aud1vol
	move.w	#2,dmacon
	bra	voice3
dovoice2:
	cmp.b	#1,triolecount2
	bne	norestwart2
	move.w	triolerest2,long2
	beq	norestwart2
	clr.w	triolerest2
	clr.b	triolecount2
	bra	voice3
norestwart2:
	moveq	#0,d0
	moveq	#0,d1
	addq.w	#1,point2
	move.w	point2,d0
	asl.w	#1,d0
	move.l	voice2mem,a0
	move.b	1(a0,d0),d1
	bne	noendsong2
	clr.b	repc2
	move.w	#1,point2
	moveq	#2,d0
	move.b	1(a0,d0),d1
	beq	voice3
noendsong2:
	cmp.b	#255,d1
	beq	dovoice2
	cmp.b	#254,d1
	beq	dovoice2
	cmp.b	#191,d1
	beq	dovoice2
	cmp.b	#190,d1
	beq	dovoice2
	cmp.b	#189,d1
	beq	dovoice2
	tst.b	d1
	bpl	noszeich2
	bsr	dowhatwelle
	cmp.b	#9,d2
	beq	nowellset2
	move.b	d2,doshortinst2
	bra	dovoice2
nowellset2:
	bsr	dowhatvmod
	cmp.b	#9,d2
	beq	novolmodset2
	move.b	d2,volmod2
	bra	dovoice2
novolmodset2:
	bsr	dowhatfmod
	cmp.b	#9,d2
	beq	nofreqmodset2
	move.b	d2,freqmod2
	bra	dovoice2
nofreqmodset2:
	bsr	dowhatinst
	tst.l	d2
	beq	noinstsetv2
	clr.b	doshortinst2
	move.l	d2,instvoice2
	move.l	d3,bodyvoice2
	bra	dovoice2
noinstsetv2:
	cmp.b	#217,d1
	bne	nostonpl2
	move.b	#1,stackato2
	bra	dovoice2
nostonpl2:
	cmp.b	#216,d1
	bne	nostoffpl2
	clr.b	stackato2
	bra	dovoice2
nostoffpl2:
	cmp.b	#230,d1
	bne	norepstapl2
	cmp.b	#19,repc2
	beq	dovoice2
	addq.b	#1,repc2
	move.b	repc2,d1
	asl.b	#1,d1
	lea	reps2,a0
	move.w	point2,0(a0,d1)
	bra	dovoice2
norepstapl2:
	cmp.b	#229,d1
	bne	norependpl2
	move.b	repc2,d1
	asl.b	#1,d1
	lea	reps2,a0
	move.w	point2,d0
	cmp.w	(a0,d1),d0
	bne	wieder2
	clr.w	0(a0,d1)
	cmp.b	#0,repc2
	beq	dovoice2
	sub.b	#1,repc2
	bra	dovoice2
wieder2:
	move.w	(a0,d1),point2
	move.w	d0,(a0,d1)
	bra	dovoice2
norependpl2:
	cmp.b	#240,d1
	bne	nofermate2
	move.b	#255,fermateflag
	bra	dovoice2
nofermate2:
	cmp.b	#253,d1
	bne	noritar2
	cmp.b	#7,speedplay
	beq	dovoice2
	addq.b	#1,speedplay
	bra	dovoice2
noritar2:
	cmp.b	#252,d1
	bne	noaccel2
	tst.b	speedplay
	beq	dovoice2
	subq.b	#1,speedplay
	bra	dovoice2
noaccel2:
	bsr	dowhatlaut
	tst.w	d2
	beq	nonewlaut2
	move.w	d2,vol2
	bra	dovoice2
nonewlaut2:
	cmp.b	#247,d1
	bne	nocrescendo2
	clr.b	decr2
	move.b	#4,cres2
	bra	dovoice2
nocrescendo2:
	cmp.b	#248,d1
	bne	nodecrescendo2
	clr.b	cres2
	move.b	#4,decr2
	bra	dovoice2
nodecrescendo2:
	cmp.b	#239,d1
	bne	notriolst2
	move.b	#4,triolecount2
	bra	dovoice2
notriolst2:
	cmp.b	#220,d1
	bne	noduolst2
	move.b	#2,duolecount2
	bra	dovoice2
noduolst2:
	cmp.b	#219,d1
	bne	nobho2
	move.b	#255,bogenflag2
	move.b	high2,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice2
	move.w	#2,dmacon
	bra	dovoice2
nobho2:
	cmp.b	#218,d1
	bne	nobti2
	move.b	#255,bogenflag2
	move.b	high2,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice2
	move.w	#2,dmacon 
	bra	dovoice2
nobti2:
noszeich2:
	tst.b	cres2
	beq	nodocres2
	subq.b	#1,cres2
	cmp.w	#64,vol2
	bge	nodocres2
	addq.w	#4,vol2
nodocres2:
	tst.b	decr2
	beq	nododecr2
	subq.b	#1,decr2
	cmp.w	#0,vol2
	bls	nododecr2
	subq.w	#4,vol2
nododecr2:
	asl.w	#1,d1
	lea	longtab,a1
	move.w	0(a1,d1),d2
	moveq	#0,d7
	move.b	speedplay,d7
	addq.b	#1,d7
	mulu	d7,d2
	tst.b	fermateflag
	beq	nodoferm2
	asl.w	#1,d2
	clr.b	fermateflag
nodoferm2:
	tst.b	duolecount2
	beq	noduopl2
	subq.b	#1,duolecount2
	move.l	d2,d7
	add.w	d7,d2
	add.w	d7,d2
	lsr.w	#1,d2
noduopl2:
	cmp.b	#1,triolecount2
	bls	nodotriole2
	subq.b	#1,triolecount2
	asl.w	#1,d2
	divu	#3,d2
	swap	d2
	move.w	d2,triolerest2
	swap	d2
nodotriole2:
	move.w	d2,long2
	lsr.w	#1,d2
	move.w	d2,stlong2
	moveq   #0,d1
	move.b	0(a0,d0),d1
	bne	isnote2
	move.b	#1,paused2
	bra	voice3
isnote2:
	clr.b	paused2
	move.b	d1,high2
	moveq	#0,d4
	move.l	d1,d3
	divu	#12,d3
	add.w	d3,d4
	addq.b	#1,d4
	move.l	d4,okt2
	move.l	d4,allokt
	tst.b	doshortinst2
	beq	noshortplay2
	moveq	#0,d0
	move.b	doshortinst2,d0
	subq.b	#1,d0
	asl.w	#8,d0
	asl.w	#3,d0
	move.l	megamem,a0
	adda.l	d0,a0
	move.l	a0,aud1lch
	move.w	#1024,aud1len
	move.l	#3579546,d0
	asl.w	#1,d1
	lea	periodtab,a1
	move.w	0(a1,d1),d1
	asl.w	#4,d1
	divu	d1,d0
	move.w	d0,aud1per
	move.w	d0,period2
	clr.l	okt2
	bra	goshot2
noshortplay2:
	move.l	bodyvoice2,d4
	move.l	instvoice2,a3
	bsr	ermnotes
	move.l	d4,aud1lch
	move.w	d7,aud1len
	move.w	d0,aud1per
	move.w	d0,period2
	move.l	20(a3),d3
	bne	oneshot2
	bsr	longpart2
oneshot2:
	tst.b	bogenflag2
	beq	goshot2
	clr.b	bogenflag2
	bsr	longpart2
	tst.l	24(a3)
	beq	dropshot2
goshot2:
	move.w	#$8202,dmacon
	move.w	vol2,aud1vol
dropshot2:
	clr.b	freqcount2
	clr.b	volmcount2
	moveq	#70,d0
	divu	long2,d0
	move.b	d0,modvoladd2
	move.b	d0,modfreqadd2
	bne	noadd2volm
	move.b	#255,modvoladd2
	move.b	#255,modfreqadd2
noadd2volm:
	bsr	modvolume2
	move.l	24(a3),d3
	bne	voice3
	move.l	#10,okt2

voice3:				;dasselbe nochmal für
	tst.b	stackato2
	beq	vvoice3		;die gute alte Stimme 3
	tst.w	stlong2
	bne	vvoice3
	move.w	#0,aud1vol
vvoice3:
	tst.w	stlong3
	beq	nosslo3
	subq.w	#1,stlong3
nosslo3:
	bsr	modvolume3
	bsr	modfrequenz3
	subq.w	#1,long3
	beq	dovoice3
	cmp.w	#1,long3
	bne	voice4
	moveq	#0,d0
	move.w	point3,d0
	asl.w	#1,d0
	move.l	voice3mem,a0
	cmp.b	#219,3(a0,d0)
	beq	voice4
	cmp.b	#218,3(a0,d0)
	beq	voice4
	move.w	#0,aud2vol
	move.w	#4,dmacon
	bra	voice4
dovoice3:
	cmp.b	#1,triolecount3
	bne	norestwart3
	move.w	triolerest3,long3
	beq	norestwart3
	clr.w	triolerest3
	clr.b	triolecount3
	bra	voice4
norestwart3:
	moveq	#0,d0
	moveq	#0,d1
	addq.w	#1,point3
	move.w	point3,d0
	asl.w	#1,d0
	move.l	voice3mem,a0
	move.b	1(a0,d0),d1
	bne	noendsong3
	clr.b	repc3
	move.w	#1,point3
	moveq	#2,d0
	move.b	1(a0,d0),d1
	beq	voice4
noendsong3:
	cmp.b	#255,d1
	beq	dovoice3
	cmp.b	#254,d1
	beq	dovoice3
	cmp.b	#191,d1
	beq	dovoice3
	cmp.b	#190,d1
	beq	dovoice3
	cmp.b	#189,d1
	beq	dovoice3
	tst.b	d1
	bpl	noszeich3
	bsr	dowhatwelle
	cmp.b	#9,d2
	beq	nowellset3
	move.b	d2,doshortinst3
	bra	dovoice3
nowellset3:
	bsr	dowhatvmod
	cmp.b	#9,d2
	beq	novolmodset3
	move.b	d2,volmod3
	bra	dovoice3
novolmodset3:
	bsr	dowhatfmod
	cmp.b	#9,d2
	beq	nofreqmodset3
	move.b	d2,freqmod3
	bra	dovoice3
nofreqmodset3:
	bsr	dowhatinst
	tst.l	d2
	beq	noinstsetv3
	clr.b	doshortinst3
	move.l	d2,instvoice3
	move.l	d3,bodyvoice3
	bra	dovoice3
noinstsetv3:
	cmp.b	#217,d1
	bne	nostonpl3
	move.b	#1,stackato3
	bra	dovoice3
nostonpl3:
	cmp.b	#216,d1
	bne	nostoffpl3
	clr.b	stackato3
	bra	dovoice3
nostoffpl3:
	cmp.b	#230,d1
	bne	norepstapl3
	cmp.b	#19,repc3
	beq	dovoice3
	addq.b	#1,repc3
	move.b	repc3,d1
	asl.b	#1,d1
	lea	reps3,a0
	move.w	point3,0(a0,d1)
	bra	dovoice3
norepstapl3:
	cmp.b	#229,d1
	bne	norependpl3
	move.b	repc3,d1
	asl.b	#1,d1
	lea	reps3,a0
	move.w	point3,d0
	cmp.w	(a0,d1),d0
	bne	wieder3
	clr.w	0(a0,d1)
	cmp.b	#0,repc3
	beq	dovoice3
	sub.b	#1,repc3
	bra	dovoice3
wieder3:
	move.w	(a0,d1),point3
	move.w	d0,(a0,d1)
	bra	dovoice3
norependpl3:
	cmp.b	#240,d1
	bne	nofermate3
	move.b	#255,fermateflag
	bra	dovoice3
nofermate3:
	cmp.b	#253,d1
	bne	noritar3
	cmp.b	#7,speedplay
	beq	dovoice3
	addq.b	#1,speedplay
	bra	dovoice3
noritar3:
	cmp.b	#252,d1
	bne	noaccel3
	tst.b	speedplay
	beq	dovoice3
	subq.b	#1,speedplay
	bra	dovoice3
noaccel3:
	bsr	dowhatlaut
	tst.w	d2
	beq	nonewlaut3
	move.w	d2,vol3
	bra	dovoice3
nonewlaut3:
	cmp.b	#247,d1
	bne	nocrescendo3
	clr.b	decr3
	move.b	#4,cres3
	bra	dovoice3
nocrescendo3:
	cmp.b	#248,d1
	bne	nodecrescendo3
	clr.b	cres3
	move.b	#4,decr3
	bra	dovoice3
nodecrescendo3:
	cmp.b	#239,d1
	bne	notriolst3
	move.b	#4,triolecount3
	bra	dovoice3
notriolst3:
	cmp.b	#220,d1
	bne	noduolst3
	move.b	#2,duolecount3
	bra	dovoice3
noduolst3:
	cmp.b	#219,d1
	bne	nobho3
	move.b	#255,bogenflag3
	move.b	high3,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice3
	move.w	#4,dmacon
	bra	dovoice3
nobho3:
	cmp.b	#218,d1
	bne	nobti3
	move.b	#255,bogenflag3
	move.b	high3,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice3
	move.w	#4,dmacon
	bra	dovoice3
nobti3:
noszeich3:
	tst.b	cres3
	beq	nodocres3
	subq.b	#1,cres3
	cmp.w	#64,vol3
	bge	nodocres3
	addq.w	#4,vol3
nodocres3:
	tst.b	decr3
	beq	nododecr3
	subq.b	#1,decr3
	cmp.w	#0,vol3
	bls	nododecr3
	subq.w	#4,vol3
nododecr3:
	asl.w	#1,d1
	lea	longtab,a1
	move.w	0(a1,d1),d2
	moveq	#0,d7
	move.b	speedplay,d7
	addq.b	#1,d7
	mulu	d7,d2
	tst.b	fermateflag
	beq	nodoferm3
	asl.w	#1,d2
	clr.b	fermateflag
nodoferm3:
	tst.b	duolecount3
	beq	noduopl3
	subq.b	#1,duolecount3
	move.l	d2,d7
	add.w	d7,d2
	add.w	d7,d2
	lsr.w	#1,d2
noduopl3:
	cmp.b	#1,triolecount3
	bls	nodotriole3
	subq.b	#1,triolecount3
	asl.w	#1,d2
	divu	#3,d2
	swap	d2
	move.w	d2,triolerest3
	swap	d2
nodotriole3:
	move.w	d2,long3
	lsr.w	#1,d2
	move.w	d2,stlong3
	moveq	#0,d1
	move.b	0(a0,d0),d1
	bne	isnote3
	move.b	#1,paused3
	bra	voice4
isnote3:
	clr.b	paused3
	moveq	#0,d4
	move.b	d1,high3
	move.l	d1,d3
	addq.b	#1,d4
	divu	#12,d3
	add.w	d3,d4
	move.l	d4,okt3
	move.l	d4,allokt
	tst.b	doshortinst3
	beq	noshortplay3
	moveq	#0,d0
	move.b	doshortinst3,d0
	subq.b	#1,d0
	asl.w	#8,d0
	asl.w	#3,d0
	move.l	megamem,a0
	adda.l	d0,a0
	move.l	a0,aud2lch
	move.w	#1024,aud2len
	move.l	#3579546,d0
	asl.w	#1,d1
	lea	periodtab,a1
	move.w	0(a1,d1),d1
	asl.w	#4,d1
	divu	d1,d0
	move.w	d0,aud2per
	move.w	d0,period3
	clr.l	okt3
	bra	goshot3
noshortplay3:
	move.l	bodyvoice3,d4
	move.l	instvoice3,a3
	bsr	ermnotes
	move.l	d4,aud2lch
	move.w	d0,aud2per
	move.w	d0,period3
	move.w	d7,aud2len
	move.l	20(a3),d3
	bne	oneshot3
	bsr	longpart3
oneshot3:
	tst.b	bogenflag3
	beq	goshot3
	clr.b	bogenflag3
	bsr	longpart3
	tst.l	24(a3)
	beq	dropshot3
goshot3:
	move.w	#$8204,dmacon
	move.w	vol3,aud2vol
dropshot3:
	clr.b	freqcount3
	clr.b	volmcount3
	moveq	#70,d0
	divu	long3,d0
	move.b	d0,modvoladd3
	move.b	d0,modfreqadd3
	bne	noadd3volm
	move.b	#255,modvoladd3
	move.b	#255,modfreqadd3
noadd3volm:
	bsr	modvolume3
	move.l	24(a3),d3
	bne	voice4
	move.l	#10,okt3

voice4:
	tst.b	stackato3		;siehe wieder Stimme 1
	beq	vvoice4
	tst.w	stlong3
	bne	vvoice4
	move.w	#0,aud2vol
vvoice4:
	tst.w	stlong4
	beq	nosslo4
	subq.w	#1,stlong4
nosslo4:
	bsr	modvolume4
	bsr	modfrequenz4
	subq.w	#1,long4
	beq	dovoice4
	cmp.w	#1,long4
	bne	novoice
	moveq	#0,d0
	move.w	point4,d0
	asl.w	#1,d0
	move.l	voice4mem,a0
	cmp.b	#219,3(a0,d0)
	beq	novoice
	cmp.b	#218,3(a0,d0)
	beq	novoice
	move.w	#0,aud3vol
	move.w	#8,dmacon
	bra	novoice
dovoice4:
	cmp.b	#1,triolecount4
	bne	norestwart4
	move.w	triolerest4,long4
	beq	norestwart4
	clr.w	triolerest4
	clr.b	triolecount4
	bra	novoice
norestwart4:
	moveq	#0,d0
	moveq	#0,d1
	addq.w	#1,point4
	move.w	point4,d0
	asl.w	#1,d0
	move.l	voice4mem,a0
	move.b	1(a0,d0),d1
	bne	noendsong4
	clr.b	repc4
	move.w	#1,point4
	moveq	#2,d0
	move.b	1(a0,d0),d1
	beq	novoice
noendsong4:
	cmp.b	#255,d1
	beq	dovoice4
	cmp.b	#254,d1
	beq	dovoice4
	cmp.b	#191,d1
	beq	dovoice4
	cmp.b	#190,d1
	beq	dovoice4
	cmp.b	#189,d1
	beq	dovoice4
	tst.b	d1
	bpl	noszeich4
	bsr	dowhatwelle
	cmp.b	#9,d2
	beq	nowellset4
	move.b	d2,doshortinst4
	bra	dovoice4
nowellset4:
	bsr	dowhatvmod
	cmp.b	#9,d2
	beq	novolmodset4
	move.b	d2,volmod4
	bra	dovoice4
novolmodset4:
	bsr	dowhatfmod
	cmp.b	#9,d2
	beq	nofreqmodset4
	move.b	d2,freqmod4
	bra	dovoice4
nofreqmodset4:
	bsr	dowhatinst
	tst.l	d2
	beq	noinstsetv4
	clr.b	doshortinst4
	move.l	d2,instvoice4
	move.l	d3,bodyvoice4
	bra	dovoice4
noinstsetv4:
	cmp.b	#217,d1
	bne	nostonpl4
	move.b	#1,stackato4
	bra	dovoice4
nostonpl4:
	cmp.b	#216,d1
	bne	nostoffpl4
	clr.b	stackato4
	bra	dovoice4
nostoffpl4:
	cmp.b	#230,d1
	bne	norepstapl4
	cmp.b	#19,repc4
	beq	dovoice4
	addq.b	#1,repc4
	move.b	repc4,d1
	asl.b	#1,d1
	lea	reps4,a0
	move.w	point4,0(a0,d1)
	bra	dovoice4
norepstapl4:
	cmp.b	#229,d1
	bne	norependpl4
	move.b	repc4,d1
	asl.b	#1,d1
	lea	reps4,a0
	move.w	point4,d0
	cmp.w	(a0,d1),d0
	bne	wieder4
	clr.w	0(a0,d1)
	cmp.b	#0,repc4
	beq	dovoice4
	sub.b	#1,repc4
	bra	dovoice4
wieder4:
	move.w	(a0,d1),point4
	move.w	d0,(a0,d1)
	bra	dovoice4
norependpl4:
	cmp.b	#240,d1
	bne	nofermate4
	move.b	#255,fermateflag
	bra	dovoice4
nofermate4:
	cmp.b	#253,d1
	bne	noritar4
	cmp.b	#7,speedplay
	beq	dovoice4
	addq.b	#1,speedplay
	bra	dovoice4
noritar4:
	cmp.b	#252,d1
	bne	noaccel4
	tst.b	speedplay
	beq	dovoice4
	subq.b	#1,speedplay
	bra	dovoice4
noaccel4:
	bsr	dowhatlaut
	tst.w	d2
	beq	nonewlaut4
	move.w	d2,vol4
	bra	dovoice4
nonewlaut4:
	cmp.b	#247,d1
	bne	nocrescendo4
	clr.b	decr4
	move.b	#4,cres4
	bra	dovoice4
nocrescendo4:
	cmp.b	#248,d1
	bne	nodecrescendo4
	clr.b	cres4
	move.b	#4,decr4
	bra	dovoice4
nodecrescendo4:
	cmp.b	#239,d1
	bne	notriolst4
	move.b	#4,triolecount4
	bra	dovoice4
notriolst4:
	cmp.b	#220,d1
	bne	noduolst4
	move.b	#2,duolecount4
	bra	dovoice4
noduolst4:
	cmp.b	#219,d1
	bne	nobho4
	move.b	#255,bogenflag4
	move.b	high4,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice4
	move.w	#8,dmacon
	bra	dovoice4
nobho4:
	cmp.b	#218,d1
	bne	nobti4
	move.b	#255,bogenflag4
	move.b	high4,d1
	cmp.b	2(a0,d0),d1
	beq	dovoice4
	move.w	#8,dmacon
	bra	dovoice4
nobti4:
noszeich4:
	tst.b	cres4
	beq	nodocres4
	subq.b	#1,cres4
	cmp.w	#64,vol4
	bge	nodocres4
	addq.w	#4,vol4
nodocres4:
	tst.b	decr4
	beq	nododecr4
	subq.b	#1,decr4
	cmp.w	#0,vol4
	bls	nododecr4
	subq.w	#4,vol4
nododecr4:
	asl.w	#1,d1
	lea	longtab,a1
	move.w	0(a1,d1),d2
	moveq	#0,d7
	move.b	speedplay,d7
	addq.b	#1,d7
	mulu	d7,d2
	tst.b	fermateflag
	beq	nodoferm4
	asl.w	#1,d2
	clr.b	fermateflag
nodoferm4:
	tst.b	duolecount4
	beq	noduopl4
	subq.b	#1,duolecount4
	move.l	d2,d7
	add.w	d7,d2
	add.w	d7,d2
	lsr.w	#1,d2
noduopl4:
	cmp.b	#1,triolecount4
	bls	nodotriole4
	subq.b	#1,triolecount4
	asl.w	#1,d2
	divu	#3,d2
	swap	d2
	move.w	d2,triolerest4
	swap	d2
nodotriole4:
	move.w	d2,long4
	lsr.w	#1,d2
	move.w	d2,stlong4
	moveq	#0,d1
	move.b	0(a0,d0),d1
	bne	isnote4
	move.b	#1,paused4
	bra	novoice
isnote4:
	clr.b	paused4
	move.b	d1,high4
	moveq	#0,d4
	move.l	d1,d3
	divu	#12,d3
	add.w	d3,d4
	addq.b	#1,d4
	move.l	d4,okt4
	move.l	d4,allokt
	tst.b	doshortinst4
	beq	noshortplay4
	moveq	#0,d0
	move.b	doshortinst4,d0
	subq.b	#1,d0
	asl.w	#8,d0
	asl.w	#3,d0
	move.l	megamem,a0
	adda.l	d0,a0
	move.l	a0,aud3lch
	move.w	#1024,aud3len
	move.l	#3579546,d0
	asl.w	#1,d1
	lea	periodtab,a1
	move.w	0(a1,d1),d1
	asl.w	#4,d1
	divu	d1,d0
	move.w	d0,aud3per
	move.w	d0,period4
	clr.l	okt4
	bra	goshot4
noshortplay4:
	move.l	bodyvoice4,d4
	move.l	instvoice4,a3
	bsr	ermnotes
	move.l	d4,aud3lch
	move.w	d7,aud3len
	move.w	d0,aud3per
	move.w	d0,period4
	move.l	20(a3),d3
	bne	oneshot4
	bsr	longpart4
oneshot4:
	tst.b	bogenflag4
	beq	goshot4
	clr.b	bogenflag4
	bsr	longpart4
	tst.l	24(a3)
	beq	dropshot4
goshot4:
	move.w	#$8208,dmacon
	move.w	vol4,aud3vol
dropshot4:
	clr.b	freqcount4
	clr.b	volmcount4
	moveq	#70,d0
	divu	long4,d0
	move.b	d0,modvoladd4
	move.b	d0,modfreqadd4
	bne	noadd4volm
	move.b	#255,modvoladd4
	move.b	#255,modfreqadd4
noadd4volm:
	bsr	modvolume4
	move.l	24(a3),d3
	bne	novoice
	move.l	#10,okt4

novoice:
	tst.b	stackato4
	beq	novvoice
	tst.w	stlong4
	bne	novvoice
	move.w	#0,aud3vol
novvoice:
	bsr	longpart1	;Daten für Longparts
	bsr	longpart2
	bsr	longpart3	;der Instrumente ermitteln
	bsr	longpart4
	movem.l	(sp)+,d1-d7/a1-a6	;Register zurückschreiben
	rts

; *** Frequenzmodulation durchführen ***

modfrequenz1:
	tst.b	paused1		;Prüfen, ob Pause gespielt wird
	bne	nofreqmod1	;=> keine Modulation
	tst.b	freqmod1	;Prüfen, ob Modulation erwünscht
	beq	nofreqmod1	;ist
	cmp.b	#69,freqcount1	;Prüfen, ob Modulationszähler am
	bne	okfmod1		;Ende ist und Zähler
	clr.b	freqcount1	;gegebenenfalls zurücksetzen
okfmod1:
	cmp.b	#255,modfreqadd1	;Prüfen, ob 'Spezialbehandlung'
	bne	okokfm1		;für extra lange Noten nötig ist
	move.b	#254,modfreqadd1	;d.h. eine Modulation übersprungen
	bra	nofreqmod1	;werden muß
okokfm1:
	moveq	#0,d0
	moveq	#0,d2
	move.b	freqmod1,d0	;Nummer der Modulationskurve
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	#490,a0		;Modulationsdaten errechnen
	adda.l	d0,a0
	moveq	#0,d0		;Schrittzähler der Modulation
	move.b	freqcount1,d0	;lesen und
	move.w	period1,d1	;normalen Periodwert
	move.b	0(a0,d0),d2
	btst	#7,d2		;mit Modulationskurvenwert
	beq	addmodf1
	bclr	#7,d2		;verrechnen
	lsr.l	#1,d2
	sub.w	d2,d1
	bpl	domodf1		;Modulation nach unten oder
	moveq	#0,d1
	bra	domodf1
addmodf1:
	lsr.l	#1,d2		;nach oben durchführen und
	add.w	d2,d1
domodf1:
	move.w	d1,aud0per	;neuen Periodwert setzen
	move.b	modfreqadd1,d1
	cmp.b	#254,d1		;Prüfen, ob Spezialbehandlung
	bne	okadfm1		;erforderlich ist und wenn nötig
	move.b	#255,modfreqadd1	;Flag für Überspringen beim
	moveq	#1,d1		;nächsten Blank setzen
okadfm1:
	add.b	d1,freqcount1	;Schrittzähler erhöhen
nofreqmod1:
	rts			;und fertig !
modfrequenz2:
	tst.b	paused2
	bne	nofreqmod2	;Hier dasselbe für die
	tst.b	freqmod2
	beq	nofreqmod2	;Frequenzmodulation in
	cmp.b	#69,freqcount2
	bne	okfmod2		;Stimme 2
	clr.b	freqcount2
okfmod2:
	cmp.b	#255,modfreqadd2
	bne	okokfm2
	move.b	#254,modfreqadd2
	bra	nofreqmod2
okokfm2:
	moveq	#0,d0
	moveq	#0,d2
	move.b	freqmod2,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	#490,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	freqcount2,d0
	move.w	period2,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodf2
	bclr	#7,d2
	lsr.l	#1,d2
	sub.w	d2,d1
	bpl	domodf2
	moveq	#0,d1
	bra	domodf2
addmodf2:
	lsr.l	#1,d2
	add.w	d2,d1
domodf2:
	move.w	d1,aud1per
	move.b	modfreqadd2,d1
	cmp.b	#254,d1
	bne	okadfm2
	move.b	#255,modfreqadd2
	moveq	#1,d1
okadfm2:
	add.b	d1,freqcount2
nofreqmod2:
	rts
modfrequenz3:			;Und die Frequenzmodulation
	tst.b	paused3
	bne	nofreqmod3	;für Stimmme 3
	tst.b	freqmod3
	beq	nofreqmod3
	cmp.b	#69,freqcount3
	bne	okfmod3
	clr.b	freqcount3
okfmod3:
	cmp.b	#255,modfreqadd3
	bne	okokfm3
	move.b	#254,modfreqadd3
	bra	nofreqmod3
okokfm3:
	moveq	#0,d0
	moveq	#0,d2
	move.b	freqmod3,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	#490,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	freqcount3,d0
	move.w	period3,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodf3
	bclr	#7,d2
	lsr.l	#1,d2
	sub.w	d2,d1
	bpl	domodf3
	moveq	#0,d1
	bra	domodf3
addmodf3:
	lsr.l	#1,d2
	add.w	d2,d1
domodf3:
	move.w	d1,aud2per
	move.b	modfreqadd3,d1
	cmp.b	#254,d1
	bne	okadfm3
	move.b	#255,modfreqadd3
	moveq	#1,d1
okadfm3:
	add.b	d1,freqcount3
nofreqmod3:
	rts
modfrequenz4:			;Und nochmal für Stimme 4
	tst.b	paused4
	bne	nofreqmod4
	tst.b	freqmod4
	beq	nofreqmod4
	cmp.b	#69,freqcount4
	bne	okfmod4
	clr.b	freqcount4
okfmod4:
	cmp.b	#255,modfreqadd4
	bne	okokfm4
	move.b	#254,modfreqadd4
	bra	nofreqmod4
okokfm4:
	moveq	#0,d0
	moveq	#0,d2
	move.b	freqmod4,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	#490,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	freqcount4,d0
	move.w	period4,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodf4
	bclr	#7,d2
	lsr.l	#1,d2
	sub.w	d2,d1
	bpl	domodf4
	moveq	#0,d1
	bra	domodf4
addmodf4:
	lsr.l	#1,d2
	add.w	d2,d1
domodf4:
	move.w	d1,aud3per
	move.b	modfreqadd4,d1
	cmp.b	#254,d1
	bne	okadfm4
	move.b	#255,modfreqadd4
	moveq	#1,d1
okadfm4:
	add.b	d1,freqcount4
nofreqmod4:
	rts

; *** Lautstärkemodulation durchführen ***

modvolume1:
	tst.b	paused1		;Wenn Pause gespielt wird
	bne	novolmod1	;gibt's keine Modulation
	tst.b	volmod1		;Und wenn keine Modulation
	beq	novolmod1	;gespielt wird auch nicht
	cmp.b	#69,volmcount1	;Prüfen, ob Schrittzähler am
	bls	okvmod1		;Ende ist und wenn nötig
	clr.b	volmcount1	;zurücksetzen
okvmod1:
	cmp.b	#255,modvoladd1	;Prüfen, ob Spezialbehandlung
	bne	okokvm1		;für extra lange Noten nötig
	move.b	#254,modvoladd1	;ist und wenn ja, dann Flag
	bra	novolmod1	;entsprechend setzen
okokvm1:
	moveq	#0,d0
	moveq	#0,d2
	move.b	volmod1,d0	;Nummer der Modulationskurve
	subq.b	#1,d0		;ermitteln und
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0	;berechnen
	adda.l	d0,a0
	moveq	#0,d0
	move.b	volmcount1,d0	;Mittels Schrittzähler
	moveq	#32,d1
	move.b	0(a0,d0),d2	;den aktullen Modulationswert
	btst	#7,d2
	beq	addmodv1	;lesen und Lautstärke
	bclr	#7,d2
	sub.b	d2,d1		;entsprechend berechnen
	bpl	domodv1
	moveq	#0,d1
	bra	domodv1
addmodv1:
	add.b	d2,d1
	cmp.b	#64,d1
	bls	domodv1
	moveq	#64,d1
domodv1:
	move.w	d1,aud0vol	;und neue Lautstärke setzen
	move.b	modvoladd1,d1	;Prüfen, ob Spezialfall für
	cmp.b	#254,d1		;extra lange Note erforderlich
	bne	okadvm1		;ist und wenn nötig Flag für
	move.b	#255,modvoladd1	;Überspringen der Modulation
	moveq	#1,d1		;beim nächsten Blank setzen
okadvm1:
	add.b	d1,volmcount1	;Schrittzähler erhöhen
novolmod1:
	rts
modvolume2:
	tst.b	paused2		;Und wieder die Lautstärke-
	bne	novolmod2
	tst.b	volmod2		;Modulation für die 2.Stimme
	beq	novolmod2
	cmp.b	#69,volmcount2
	bne	okvmod2
	clr.b	volmcount2
okvmod2:
	cmp.b	#255,modvoladd2
	bne	okokvm2
	move.b	#254,modvoladd2
	bra	novolmod2
okokvm2:
	moveq	#0,d0
	moveq	#0,d2
	move.b	volmod2,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	volmcount2,d0
	moveq   #32,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodv2
	bclr	#7,d2
	sub.b	d2,d1
	bpl	domodv2
	moveq	#0,d1
	bra	domodv2
addmodv2:
	add.b	d2,d1
	cmp.b	#64,d1
	bls	domodv2
	moveq	#64,d1
domodv2:
	move.w	d1,aud1vol
	move.b	modvoladd2,d1
	cmp.b	#254,d1
	bne	okadvm2
	move.b	#255,modvoladd2
	moveq	#1,d1
okadvm2:
	add.b	d1,volmcount2
novolmod2:
	rts
modvolume3:
	tst.b	paused3		;Und für die dritte Stimme
	bne	novolmod3
	tst.b	volmod3
	beq	novolmod3
	cmp.b	#69,volmcount3
	bne	okvmod3
	clr.b	volmcount3
okvmod3:
	cmp.b	#255,modvoladd3
	bne	okokvm3
	move.b	#254,modvoladd3
	bra	novolmod3
okokvm3:
	moveq	#0,d0
	moveq	#0,d2
	move.b	volmod3,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	volmcount3,d0
	moveq	#32,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodv3
	bclr	#7,d2
	sub.b	d2,d1
	bpl	domodv3
	moveq	#0,d1
	bra	domodv3
addmodv3:
	add.b	d2,d1
	cmp.b	#64,d1
	bls	domodv3
	moveq	#64,d1
domodv3:
	move.w	d1,aud2vol
	move.b	modvoladd3,d1
	cmp.b	#254,d1
	bne	okadvm3
	move.b	#255,modvoladd3
	moveq	#1,d1
okadvm3:
	add.b	d1,volmcount3
novolmod3:
	rts
modvolume4:
	tst.b	paused4		;Und wer hät's gedacht,
	bne	novolmod4
	tst.b	volmod4		;schließlich die Lautstärke-
	beq	novolmod4
	cmp.b	#69,volmcount4	;Modulation für die 4.Stimme
	bne	okvmod4
	clr.b	volmcount4
okvmod4:
	cmp.b	#255,modvoladd4
	bne	okokvm4
	move.b	#254,modvoladd4
	bra	novolmod4
okokvm4:
	moveq	#0,d0
	moveq	#0,d2
	move.b	volmod4,d0
	subq.b	#1,d0
	move.l	d0,d1
	asl.w	#1,d1
	asl.w	#6,d0
	add.w	d1,d0
	add.w	d1,d0
	add.w	d1,d0
	move.l	modulmem,a0
	adda.l	d0,a0
	moveq	#0,d0
	move.b	volmcount4,d0
	moveq	#32,d1
	move.b	0(a0,d0),d2
	btst	#7,d2
	beq	addmodv4
	bclr	#7,d2
	sub.b	d2,d1
	bpl	domodv4
	moveq	#0,d1
	bra	domodv4
addmodv4:
	add.b	d2,d1
	cmp.b	#64,d1
	bls	domodv4
	moveq	#64,d1
domodv4:
	move.w	d1,aud3vol
	move.b	modvoladd4,d1
	cmp.b	#254,d1
	bne	okadvm4
	move.b	#255,modvoladd4
	moveq	#1,d1
okadvm4:
	add.b	d1,volmcount4
novolmod4:
	rts

; *** Daten für LongPart_Teil des Instruments vorbereiten ***

longpart1:
	move.l	okt1,allokt	;Oktave zur Bearbeitung
	beq	nohalt1		;wenn = 0 dann nix los
	clr.l	okt1
	move.l	instvoice1,a3	;Zeiger auf InstSpeicher
	move.l	bodyvoice1,d4	;Zeiger auf BodyChunk
	bsr	ermlong		;Daten für LongPart_Teil holen
	move.l	d4,aud0lch	;Rückgabewert: Sample_Addresse
	move.w	d1,aud0len	;Rückgabewert: Sample_Länge
nohalt1:
	rts			;zurück

longpart2:			;Siehe oben
	move.l	okt2,allokt
	beq	nohalt2
	clr.l	okt2
	move.l	instvoice2,a3
	move.l	bodyvoice2,d4
	bsr	ermlong
	move.l	d4,aud1lch
	move.w	d1,aud1len
nohalt2:
	rts

longpart3:			;Siehe oben
	move.l	okt3,allokt
	beq	nohalt3
	clr.l	okt3
	move.l	instvoice3,a3
	move.l	bodyvoice3,d4
	bsr	ermlong
	move.l	d4,aud2lch
	move.w	d1,aud2len
nohalt3:
	rts

longpart4:			;Siehe oben
	move.l	okt4,allokt
	beq	nohalt4
	clr.l	okt4
	move.l	instvoice4,a3
	move.l	bodyvoice4,d4
	bsr	ermlong
	move.l	d4,aud3lch
	move.w	d1,aud3len
nohalt4:
	rts

; *** SampleLänge, Period und Addresse für OneShotPart  ***
; ***                 eines Tons ermitteln              ***
; für genauere Informationen bitte Begleittexte lesen

ermnotes:
	move.l	20(a3),d3	;oneshot_Länge plus
	add.l	24(a3),d3	;repeatpart_Länge => Gesamtlänge
	move.l	20(a3),d7	;nochmal oneshot_Länge
	move.l	#3579546,d0	;Konstante für Period_Berechnung
	asl.w	#1,d1
	lea	periodtab,a1	;Period_Wert für Ton aus
	move.w	0(a1,d1),d1	;Tabelle lesen
	cmp.l	#"RAWI",28(a3)	;Prüfen, ob ein Raw-Sample
	bne	erm8svx		;Instrument gespielt werden soll,
	mulu	rawcycle,d1	;und dann mit Raw_Hi_Cycle multipl.
	bra	ermraw
erm8svx:
	mulu	30(a3),d1	;samples_per_hicycle des Inst
ermraw:
	cmp.l	#4,allokt	;Prüfen auf Oktave 1
	bls	no1oc1		;nein ! also weiter
do1oc1:				;Oktave 1 : Period * sam_per_hi
	divu	d1,d0		; / Konstante gibt Sample_Period
	lsr.w	#1,d7		;neue Länge des Sample_Teils
	rts			;fertig
no1oc1:
	cmp.l	#3,allokt	;Prüfen auf Oktave 2
	bls	no1oc2		;nein also weiter
do1oc2:				;Oktave 2 :
	move.b	34(a3),d2	;Prüfen ob's überhaupt 2
	cmp.b	#1,d2		;Oktaven im Inst_Sample gibt
	bls	do1oc1
	add.l	d3,d4		;Sample_Teil für Okt1 überspringen
	asl.w	#1,d1		;Oktave 2 => Period mal 2
	divu	d1,d0		;Sample_Period berechnen
	rts			;fertig
no1oc2:
	cmp.l	#2,allokt	;Prüfen auf Oktave 3
	bls	no1oc3		;nein also weiter
do1oc3:				;Oktave 3 :
	move.b	34(a3),d2	;Prüfen ob's überhaupt 3
	cmp.b	#2,d2		;Oktaven im Inst_Sample gibt
	bls	do1oc2
	move.l	d3,d6
	add.l	d6,d3		;Sample_Teil für Okt1 und
	add.l	d6,d3
	add.l	d3,d4		;Okt2 überspringen
	asl.w	#2,d1
	divu	d1,d0		;Sample_Period berechnen
	asl.w	#1,d7		;neue Länge des Sample_Teils
	rts
no1oc3:
	cmp.l	#1,allokt	;Siehe oben
	bls	no1oc4
do1oc4:
	move.b	34(a3),d2
	cmp.b	#3,d2
	bls	do1oc3
	move.l	d3,d6
	asl.l	#3,d3
	sub.l	d6,d3
	add.l	d3,d4
	asl.w	#3,d1
	divu	d1,d0
	asl.w	#2,d7
	rts
no1oc4:				;Siehe oben
	move.b	34(a3),d2
	cmp.b	#4,d2
	bls	do1oc4
	move.l	d3,d6
	asl.l	#4,d3
	sub.l	d6,d3
	add.l	d3,d4
	asl.w	#4,d1
	divu	d1,d0
	asl.w	#3,d7
	rts

; *** Sample_Länge, _Period und _Addresse des LongPart_Teils ***
; ***               eines Tons ermitteln                     ***
; für genauere Informationen bitte Begleittexte lesen

ermlong:
	move.l	20(a3),d3	;Länge des OneShot_Part
	move.l	24(a3),d1	;Länge des Long_Part
	move.l	24(a3),d7	;Lämge des Long_Part
	cmp.l	#10,allokt	;Prüfen, ob gar kein
	bne	no1nono		;LongPart gewünscht war
	move.l	#notone,d4	;Kein LongPart => Blindwerte setzen
	moveq	#2,d1
	clr.l	allokt		;und zurück
	rts
no1nono:
	cmp.l	#4,allokt	;Für die Berechnung der Werte
	bls	no1loc1
do1loc1:			;für den Long_Part-Teil eines
	add.l	d3,d4
	lsr.w	#1,d1		;Samples gilt dasselbe
	rts			;programmtechnische Prinzip
no1loc1:
	cmp.l	#3,allokt	;wie für die Berechnung der
	bls	no1loc2
do1loc2:			;Werte für den OneShot_Part,
	move.b	34(a3),d2
	cmp.b	#1,d2		;( siehe Routinen bei ermnotes )
	bls	do1loc1
	move.l	d3,d6
	add.l	d6,d3		;nur daß bei Berechnung
	add.l	d6,d3
	add.l	d3,d4
	add.l	d7,d4		;der Addresse des Samples
	clr.l	allokt
	rts			;jeweils noch der OneShot_Part
no1loc2:
	cmp.l	#2,allokt	;mit dazu gerechnet werden muß
	bls	no1loc3
do1loc3:			;und eben die Länge des
	move.b	34(a3),d2
	cmp.b	#2,d2		;Long_Parts als Sample_Länge
	bls	do1loc2
	move.l	d3,d6
	asl.l	#3,d3		;übergeben wird
	sub.l	d6,d3
	add.l	d3,d4
	move.l	d7,d6
	add.l	d6,d7
	add.l	d6,d7
	add.l	d7,d4
	asl.w	#1,d1
	clr.l	allokt
	rts
no1loc3:
	cmp.l	#1,allokt	;siehe oben
	bls	no1loc4
do1loc4:
	move.b	34(a3),d2
	cmp.b	#3,d2
	bls	do1loc3
	move.l	d3,d6
	asl.l	#4,d3
	sub.l	d6,d3
	add.l	d3,d4
	move.l	d7,d6
	asl.l	#3,d7
	sub.l	d6,d7
	add.l	d7,d4
	asl.w	#2,d1
	clr.l	allokt
	rts
no1loc4:			;siehe oben
	move.b	34(a3),d2
	cmp.b	#4,d2
	bls	do1loc4
	move.l	d3,d6
	asl.l	#5,d3
	sub.l	d6,d3
	add.l	d3,d4
	move.l	d7,d6
	asl.l	#4,d7
	sub.l	d6,d7
	add.l	d7,d4
	asl.w	#3,d1
	clr.l	allokt
	rts

; *** Prüfen, ob neuer Instrumentenaufruf gefragt ist ***

dowhatinst:
	moveq	#0,d2
	moveq	#0,d3
	lea	inst1mem,a4	;Zeiger auf Instr-Adressen
	lea	body1mem,a5	;Zeiger auf Instr-Body-Chunks
	lea	instwerttab,a3	;Zeiger Instwerttabelle
	moveq	#15,d4		;16 Instrumente können's sein
dowhatiloop:
	cmp.b	0(a3,d4),d1	;Instrumentenkennung gefunden ?
	beq	gotwhati	;ja ... weiter unten
	dbra	d4,dowhatiloop	;nein ... weiter suchen
	rts
gotwhati:
	asl.w	#2,d4		;Zeiger auf Position in den
	move.l	0(a4,d4),d2	;Tabellen und entsprechende
	move.l	0(a5,d4),d3	;Werte lesen
	rts

; *** Prüfen, ob und wenn ja, welche neue Lautstärke ***

dowhatlaut:
	moveq	#0,d2
	cmp.b	#240,d1		;Lautstärke zu setzen ?
	bls	nodolaut
	cmp.b	#247,d1
	bge	nodolaut
	lea	lautwerttab,a1	;Ja ... entsprechenden
	sub.b	#241,d1
	move.b	0(a1,d1),d2	;Wert aus Tabelle lesen
nodolaut:
	rts

; *** Prüfen, welche Lautstärkenmodulation gesetzt werden soll ***

dowhatvmod:
	moveq	#9,d2
	cmp.b	#207,d1		;Lautstärkenmodulation zu
	bls	nodovmod
	cmp.b	#216,d1		;setzen ?
	bge	nodovmod
	lea	modtab,a1	;Ja ... entsprechenden
	sub.b	#208,d1
	move.b	0(a1,d1),d2	;Wert aus Tabelle lesen
nodovmod:
	rts

; *** Prüfen, welche Frequenzmodulation gesetzt werden soll ***

dowhatfmod:
	moveq	#9,d2
	cmp.b	#199,d1		;Frequenzmodulation zu
	bls	nodofmod
	cmp.b	#208,d1		;setzen ?
	bge	nodofmod
	lea	modtab,a1	;Ja ... entsrpechenden
	sub.b	#200,d1
	move.b	0(a1,d1),d2	;Wert aus Tabelle lesen
nodofmod:
	rts

; *** Prüfen, welche Wellenform gesetzt werden soll ***

dowhatwelle:
	moveq	#9,d2
	cmp.b	#191,d1		;Wellenformaufruf zu
	bls	nodowelle
	cmp.b	#200,d1		;setzen ?
	bge	nodowelle
	sub.b	#191,d1		;Ja ... entsprechenden Wert
	move.b	d1,d2		;ermitteln
nodowelle:
	rts

; Nachfolgend die Tabellen der Variablen und Konstanten, die
; von den einzelnen Routinen benötigt werden.

; *** Instrumentendirectory ***

; wenn es sich bei dem zu spielenden Song nicht um einen Komplett-
; song handelt, der die nötigen Instrumentendaten direkt enthält,
; setzen Sie hier den Pfadnamen des Directories ein, in dem sich
; die im Musikstück benötigten Instrumente befinden.

instdir:	dc.b	"Instruments",0
		even

; *** Sampleperiod-Tabelle zur Berechnung der Frequenzen ***

periodtab:	dc.w    0,65,69,73,78,82,87,92,98,104
	dc.w    110,117,123,131,139,147,156,165,175,185
	dc.w    196,208,220,233,247,262,277,294,311,330,349,370
	dc.w    392,415,440,466,494,523,554,587,622,659,698,740
	dc.w    784,831,880,932,988,1047,1109,1175,1245,1319

; Variablen/Konstanten/Zwischenspeicher usw.

dosname:	dc.b	"dos.library",0
		even
wavemem:	dc.l	0	;Zeiger auf Wellenformdaten
modulmem:	dc.l	0	;Zeiger auf Modulationsdaten
namemem:	dc.l	0	;Zeiger auf Instrumentennamen
megamem:	dc.l	0
voice1mem:	dc.l	0
voice2mem:	dc.l	0	;Zeiger auf Anfang der Notendaten
voice3mem:	dc.l	0	;der 4 Stimmen
voice4mem:	dc.l	0
filepoint:	dc.l	0	;Pointer auf Filenamen
dosbase:	dc.l	0	;Dos-Lib Basisadresse
membase:	dc.l	0	;Basisadresse des Musikstücks
memlong:	dc.l	0	;Länge des Datenfiles
filehandle:	dc.l	0	;Filehandle für Lieddatenfile
zwi1:		dc.l	0	;Zwischenspeicher für Anfangswerte
instlock:	dc.l	0	;Zwischenspeicher für Inst-Dir-Lock
oldlock:	dc.l	0	;Zwischenspeicher für altes Dir-Lock
rawcycle:	dc.l	0	;Samples_Per_Hy_Cycle für Raw-Samples

; Variablen/Konstanten für Stimmen ... 

longtab:	dc.w	0,1,2,3,4,6,8,12,16,24,32,48
instwerttab:	dc.b	231,232,233,234,235,236,237,238
		dc.b	221,222,223,224,225,226,227,228
		even	
lautwerttab:	dc.b	4,16,28,40,52,64
		even
modtab:		dc.b	1,2,3,4,5,6,7,0
		even
rawhead:	dc.b	"FORM",0,0,0,0,"8SVX","VHDR"
		dc.b	0,0,0,$14,0,0,0,0,0,0,0,0,"RAWI"
		dc.b	$20,$ab,1,0,0,1,0,0,"BODY",0,0,0,0
		even
speedwert:	dc.w	0	;Geschwindigkeit
vol1:		dc.w	0
vol2:		dc.w	0	;Lautstärken
vol3:		dc.w	0
vol4:		dc.w	0
cres1:		dc.b	0
cres2:		dc.b	0	;Zähler für Crescendo
cres3:		dc.b	0
cres4:		dc.b	0
decr1:		dc.b	0
decr2:		dc.b	0	;Zähler für Decrescendo
decr3:		dc.b	0
decr4:		dc.b	0
triolecount1:	dc.b	0
triolecount2:	dc.b	0	;Zähler für Triolen
triolecount3:	dc.b	0
triolecount4:	dc.b	0
stlong1:	dc.w	0
stlong2:	dc.w	0	;Zähler für Staccato
stlong3:	dc.w	0
stlong4:	dc.w	0
triolerest1:	dc.w	0
triolerest2:	dc.w	0	;Restzähler für Triolen
triolerest3:	dc.w	0
triolerest4:	dc.w	0
duolecount1:	dc.b	0
duolecount2:	dc.b	0	;Zähler für Duolen
duolecount3:	dc.b	0
duolecount4:	dc.b	0
bogenflag1:	dc.b	0
bogenflag2:	dc.b	0	;Flags für Haltebögen
bogenflag3:	dc.b	0
bogenflag4:	dc.b	0
stackato1:	dc.b	0
stackato2:	dc.b	0	;Flags für Staccato
stackato3:	dc.b	0
stackato4:	dc.b	0
point1:		dc.w	0	
point2:		dc.w	0	;Notenzeiger
point3:		dc.w	0
point4:		dc.w	0
long1:		dc.w	0
long2:		dc.w	0	;Zähler für Notenlänger
long3:		dc.w	0
long4:		dc.w	0
inst1mem:	ds.l	16	;Zeiger auf Speicher der Instrumente
body1mem:	ds.l	16	;Zeiger auf 'BodyChnuks'
long1mem:	ds.l	16	;Zeiger für Längen der Instrumente
bodyvoice1:	dc.l	0
bodyvoice2:	dc.l	0	;Zeiger auf 'BodyChunk'
bodyvoice3:	dc.l	0	;für die 4 Stimmen
bodyvoice4:	dc.l	0	;( betr. IFF-Format )
instvoice1:	dc.l	0
instvoice2:	dc.l	0	;Zeiger auf Speicher
instvoice3:	dc.l	0	;der Instrumente
instvoice4:	dc.l	0	;für die 4 Stimmen
allokt:		dc.l	0	;Zeiger für Oktavenermittlung
okt1:		dc.l	0
okt2:		dc.l	0	;Zeiger für Oktavenermittlung
okt3:		dc.l	0	;für die 4 Stimmen
okt4:		dc.l	0
repc1:		dc.b	0
repc2:		dc.b	0	;Wiederholungszähler
repc3:		dc.b	0
repc4:		dc.b	0
modvoladd1:	dc.b	0
modvoladd2:	dc.b	0	;Additionswert für Lautstärkemodulation
modvoladd3:	dc.b	0
modvoladd4:	dc.b	0
modfreqadd1:	dc.b	0
modfreqadd2:	dc.b	0	;Additionswert für Frequenzmodulation
modfreqadd3:	dc.b	0
modfreqadd4:	dc.b	0
high1:		dc.b	0	
high2:		dc.b	0	;Zwischenspeicher für Notenhöhe
high3:		dc.b	0
high4:		dc.b	0
doshortinst1:	dc.b	0
doshortinst2:	dc.b	0	;Flags für Wellenformen
doshortinst3:	dc.b	0
doshortinst4:	dc.b	0
freqmod1:	dc.b	0
freqmod2:	dc.b	0	;Flags für Frequenzhüllkurven
freqmod3:	dc.b	0
freqmod4:	dc.b	0
freqcount1:	dc.b	0
freqcount2:	dc.b	0	;Zähler für Frequenzmodulation
freqcount3:	dc.b	0
freqcount4:	dc.b	0
volmod1:	dc.b	0
volmod2:	dc.b	0	;Flags für Lautstärkemodulation
volmod3:	dc.b	0
volmod4:	dc.b	0
volmcount1:	dc.b	0
volmcount2:	dc.b	0	;Zähler für Lautstärkemodulation
volmcount3:	dc.b	0
volmcount4:	dc.b	0
paused1:	dc.b	0
paused2:	dc.b	0	;Flags für Pausen
paused3:	dc.b	0
paused4:	dc.b	0
period1:	dc.w	0
period2:	dc.w	0	;Zwischenspeicher für Sampleperiod
period3:	dc.w	0
period4:	dc.w	0
speedplay:	dc.b	0	;Geschwindigkeitszeiger
fermateflag:	dc.b	0	;Flag für Fermaten
versionflag:	dc.b	0	;Flag für W.O.S. 1.0 oder später
savesongflag:	dc.b	0	;Flag für Komplettsongs
		even	
reps1:		ds.w	20
reps2:		ds.w	20	; Speicher für Positionen
reps3:		ds.w	20	; bei Wiederholungen
reps4:		ds.w	20
irqmem:		ds.l	20

	section noton,data_c

notone:		dc.l	0

 END
