
	.include	"sound_mix.i"
	
	.section    	.iwram,"ax"
	.global		mix_chanels
	.align		4

mix_chanels

	stmfd	sp!,{lr}			
	
	mov	r0,#0
	
	ldr	r6,[r9,#INSTR_LOOPEND]		;loopend1
	ldr	r7,[r9,#INSTR_LOOPSTART]		;loopstart1
	ldr	r8,[r9,#INSTR_POS]		;pos1
	
	cmp	r6,r7				;loopend1 = loopstart1
	bne	chanel1noPause
	cmp	r6,r8				;loopend1 = pos1
	moveq	r0,#%01				;Chanel1 ist in Pause Modus
	moveq	r9,r10				;andere Kanal ist Master
	
chanel1noPause	
	
	ldr	r6,[r10,#INSTR_LOOPEND]		;loopend1
	ldr	r7,[r10,#INSTR_LOOPSTART]	;loopstart1
	ldr	r8,[r10,#INSTR_POS]		;pos1
	
	cmp	r6,r7				;loopend1 = loopstart1
	bne	chanel2noPause
	cmp	r6,r8				;loopend1 = pos1
	orreq	r0,r0,#%10			;Chanel1 ist in Pause Modus
	
chanel2noPause	
	
	
	addr	r2,mix_chanels_tbl
	ldr	r2,[r2,r0,lsl #2]
	mov	lr,pc
	bx	r2	
	
	ldmfd	sp!,{lr}
	bx	lr

	
mix_chanels_tbl		@dcd	mix_2to1		;beide auf nicht pause -> 2 zu 1
			@dcd	mix_1to1		;einer auf nicht pause -> 1 zu 1
			@dcd	mix_1to1		;einer auf nicht pause -> 1 zu 1
			@dcd	mix_0to1		;beide auf pause       -> 0 zu 1

;***********************************************************
;*
;* mixing 2 buffers to 1 
;*
;* r1  = output puffer
;*
;* r9  = instrumenStruktur1
;* r10 = instrumenStruktur2
;*

mix_2to1

	stmfd	sp!,{r9,r10,lr}			;sampleX1 und sampleX2 auf stack

	addr	r0,stacksave			;save sp
	str	sp,[r0]
	
	;****
			
	ldr	r6,[r9,#INSTR_LOOPEND]		;loopend1	
	ldr	r4,[r9,#INSTR_POS]		;pos1
	ldr	r5,[r9,#INSTR_FREQSTEP]		;freqstep1
	ldr	sp,[r9,#INSTR_VOLUME]		;vol1
	ldr	r0,[r9,#INSTR_SAMPLE]		;source1
	
	ldr	r12,[r10,#INSTR_LOOPEND]		;loopend2	
	ldr	r8,[r10,#INSTR_POS]		;pos2
	ldr	r11,[r10,#INSTR_FREQSTEP]	;freqstep2
	ldr	lr,[r10,#INSTR_VOLUME]		;vol2
	ldr	r7,[r10,#INSTR_SAMPLE]		;source2
	
	ldr	r9,[r9,#INSTR_LOOPSTART] 	;spos1
	ldr	r10,[r10,#INSTR_LOOPSTART] 	;spos2
	
	;**** get and mul mastervlume
	
	addr	r2,sampleXAll
	ldr	r2,[r2,#MASTER_VOLUME]		;Master Volume
	
	mul	sp,sp,r2			;*vol1
	mul	lr,lr,r2			;*vol2
	
	mov	sp,sp ,lsr #9
	mov	lr,lr ,lsr #9
	
	;**** shrink registers
	
	orr	r5,r11,r5 ,lsl #16		;freqstep1:freqstep2
	orr	sp,lr,sp ,lsl #16			;vol1:vol2	
	
	ldr	lr,=SAMPLE_BUFFER_LENGTH	
	
	;****

mixloop

	;r0 = source1			r8  = pos2
	;r1 = dest			r9  = s1adr
	;r2 = frei			r10 = s2adr
	;r3 = frei			r11 = frei
	;r4 = pos1			r12 = length2
	;r5 = freqstep1:freqstep2	r12 = length2
	;r6 = length1			lr  = count
	;r7 = source2			sp  = vol1:vol2

	;**** get data of Source1&2
	
	mov	r3,r4 ,lsr #11		;pos
	mov	r11,r8,lsr #11		;pos
	
	ldrsb	r2,[r3,r0]		;r2=[pos+adr]
	ldrsb	r3,[r11,r7]		;r3=[pos+adr]

	;**** inc pos and check loops for Source 1

	add	r4,r4,r5,lsr #16	;pos + freqstep
	cmp	r4,r6 			;epos?
	movge	r4,r9			;ja-> pos=spos
	
	;**** inc pos and check loops for Source 2
	
	mov	r11,r5 ,lsl #16
	add	r8,r8,r11,lsr #16	;pos + freqstep
	cmp	r8,r12			;epos?
	movge	r8,r10			;ja-> pos=spos
		
	;**** mix + volume
	
	mov	r11,sp,lsr #16		;vol1
	mul	r2,r2,r11		;source1*vol1
	
	bic	r11,sp,r11,lsl #16	;vol2 = vol1:vol2 AND NOT vol1<<16
	mla	r3,r3,r11,r2		;source2*vol2+source1*vol1
	
	mov	r3,r3,asr #10		;9 Vol * 2 Chanels

	;**** Boost-Schutz
	
	.ifdef	BOOST_PREVENTION
	
	cmp	r3,#127
	movge	r3,#127
	cmp	r3,#-128
	movle	r3,#-128
	
	.endif
	
	;**** schreibe
	
	strb	r3,[r1],#1

	subs	lr,lr,#1
	bne	mixloop						

	;**** get old stack		
			
	addr	r0,stacksave
	ldr	sp,[r0]	
	
	ldmfd	sp!,{r9,r10}		;sampleX1 & ampleX2
			
	str	r8,[r10,#INSTR_POS]	;save pos		
	str	r4,[r9,#INSTR_POS]	;save pos		
		
	;****	
		
	ldmfd	sp!,{lr}			;ldmfd	sp!,{pc} gibt bei batgba falschen sp ?!
	bx	lr


;***********************************************************
;*
;* mixing 1 buffers to 1 (halbe Lautstärke)
;*
;* r1  = output puffer
;*
;* r9  = instrumenStruktur1

mix_1to1

	stmfd	sp!,{lr}			;sampleX1 und sampleX2 auf stack
	
	;****
			
	ldr	r6,[r9,#INSTR_LOOPEND]		;loopend1	
	ldr	r4,[r9,#INSTR_POS]		;pos1
	ldr	r5,[r9,#INSTR_FREQSTEP]		;freqstep1
	ldr	r8,[r9,#INSTR_VOLUME]		;vol1
	ldr	r0,[r9,#INSTR_SAMPLE]		;source1
	ldr	r7,[r9,#INSTR_LOOPSTART] 	;spos1
	
	;**** get and mul mastervlume
	
	addr	r2,sampleXAll
	ldr	r2,[r2,#MASTER_VOLUME]		;Master Volume
	
	mul	r8,r8,r2			;*vol1
	mov	r8,r8 ,lsr #9			;/512
	
	;**** shrink registers
		
	ldr	lr,=SAMPLE_BUFFER_LENGTH/4	
	
	;**** Lädt 4 Bytes

mix1loop

	
	mov	r3,r4  ,lsr #11			;pos
	ldrsb	r2,[r3,r0]			;r2=[pos+adr]
	
	add	r4,r4,r5 			;pos + freqstep
	cmp	r4,r6 				;length?
	movge	r4,r7			 	;ja-> pos=spos
	
	mov	r3,r4  ,lsr #11			;pos
	ldrsb	r10,[r3,r0]			;r2=[pos+adr]
	
	add	r4,r4,r5 			;pos + freqstep
	cmp	r4,r6 				;length?
	movge	r4,r7			 	;ja-> pos=spos
	
	mov	r3,r4  ,lsr #11			;pos
	ldrsb	r11,[r3,r0]			;r2=[pos+adr]
	
	add	r4,r4,r5 			;pos + freqstep
	cmp	r4,r6 				;length?
	movge	r4,r7			 	;ja-> pos=spos
	
	mov	r3,r4  ,lsr #11			;pos
	ldrsb	r12,[r3,r0]			;r2=[pos+adr]
	
	add	r4,r4,r5 			;pos + freqstep
	cmp	r4,r6 				;length?
	movge	r4,r7			 	;ja-> pos=spos
	
	mul	r3,r2,r8			;sourcex*vol1
	mul	r10,r10,r8		
	mul	r11,r11,r8	
	mul	r12,r12,r8		
	
	mov	r3,r3 ,asr #10			;/9Vol /2		
	mov	r10,r10 ,asr #10			
	mov	r11,r11 ,asr #10			
	mov	r12,r12 ,asr #10			
	
	;r12:r11:r10:r3
	
	and	r3,r3,#$ff
	and	r10,r10,#$ff
	and	r11,r11,#$ff
	
	orr	r3,r3,r12 ,lsl #24	;r12:XX:XX:r3
	orr	r3,r3,r11 ,lsl #16	
	orr	r3,r3,r10 ,lsl #8
		
	str	r3,[r1],#4

	subs	lr,lr,#1
	bne	mix1loop						

	;**** get old stack		
							
	str	r4,[r9,#INSTR_POS]	;save pos		
		
	;****	
		
	ldmfd	sp!,{lr}			;ldmfd	sp!,{pc} gibt bei batgba falschen sp ?!
	bx	lr
	
;***********************************************************
;*
;* mixing 0 buffers to 1 (lösche buffer)
;*
;* r1  = output puffer
;*

mix_0to1

	ldr	r0,=SAMPLE_BUFFER_LENGTH/16

	mov	r2,#0
	mov	r3,#0	
	mov	r4,#0
	mov	r5,#0
	mov	r6,#0
	mov	r7,#0	
	mov	r8,#0
	mov	r9,#0
	
	mov	r10,r0 ,lsr #1		;/2
	sub	r11,r0,r10 ,lsl #1	;rest
	
mix0loop

	stmia	r1!,{r2-r9}		;lösche 32Byte
	subs	r10,r10,#1
	bne	mix0loop
	
	cmp	r11,#1
	stmeqia	r1!,{r2-r5}		;wenn 16ner Rest -> löschen
			
	bx	lr

	.end
	
	
	