⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qx.s

📁 关于DVD的MPEG2用的DSP代码,在DSP的实现MPEG的压缩,解压算法.
💻 S
字号:
;************************************************************************
; Copyright 2000 QSound Labs Inc.  All rights reserved.
;
; Revision 1.0
;
;	
;
;	Module: SUB_Qxpander (2.0 to 2.0)
;
;	Initial version: Mark S. Williams (Qsound Labs, Inc.) (19/4/2000
;	Calling	:     	Qxpander,QXinitialize,QXsave,QXrestore
;	Return:		r27
;	Param in:     	
;	Temp reg:	
;	AGR  reg:	
;	Local buffer:
;************************************************************************
;;;
;;; QXpander
;;;
;;; Copyright 2000 QSound Labs Inc.  All rights reserved.
;;;
;;; Author:	markw@qsound.com		April 19, 2000
;;;
;;; QXpander implementation for the LuxSonar DSP
;;;
;;; Modification History
;;;
;;;	April 19, 2000	mark.williams@qsound.com
;;;
;;;	code based upon qsurround implementation - paired down the processing so
;;;	that it only does the qxpander portion of qsurround.
	
#define	REMOVE_HP 0
#define THREE_STAGE 0
//#define QX_44K	
	.nolist
#include "qx.h"
	.list



#if	THREE_STAGE
#define	NumStages	3
#else
#define	NumStages	4
#endif
#define	NumDataPerStage	2
	
	.nolist
#include "regdef.h"
#ifdef SOFTWARE
#include "memory.h"
#endif
	.list

	.text
.if	QSOUND
	.globl	SUB_QXpander
	.globl	filterCoeffs
	.globl	m48both
	.globl	m44both

	.set	noreorder
	
;; --------------------------------------------------------------
;; - Code -------------------------------------------------------
;; --------------------------------------------------------------
SUB_QXpander:
	
	jsr	r28, QXrestore
	dlw	r0, QX_flag
	movi	AGRSiz0,0xffff
	movi	AGRSiz1,0xffff
	movi	AGRSiz2,0xffff
	movi	AGRSiz3,0xffff
	movi	AGRSiz4,0xffff
	tsti	r0,0
	bne	Linit_done
	jsr	r28, QXInitialise	;copy filter coeffs and states
	movi	r0, 1
	dsw	r0, QX_flag
Linit_done:	

	movi	AGRAdr2, local_FApcm_buf_byte

;; Setup address pointers
	
#if	!REMOVE_HP
	movi	AGRInc1,4
#endif
	movi	AGRInc4,4
	

	jsr	r28, QXpander		;in: local_input
					;out: pointed by AGRAdr2
					;process 256 samples
					;the result should be packed
					;as 2-channel in local_FApcm_buf_byte,
					;32-bit or 16-bit per channel depending
					;on I2S or not

	movi	AGRSiz7,0xffff

	jsr	r28, QXsave		;save states
	j	r27
	
;; --------------------------------------------------------------
;; QXrestore
;  calling: none
;  called by: SUB_QXpander
;  return: r28
;; This routine restores the status of QXpander.
;; It is called every time when we return to process QXpander. 
;; --------------------------------------------------------------

;;; MSW - Changed these to correctly account for the various combinations
;;; 	of defines....  Any change here needs to be also correctly incorporated
;;;		into the rewinding of the ptrs for the next processed sample

#if	REMOVE_HP&&THREE_STAGE
#define dmaDataSize	(15-1)
#elif REMOVE_HP&&(!THREE_STAGE)
#define dmaDataSize	(19-1)
#elif (!REMOVE_HP)&&THREE_STAGE
#define dmaDataSize (19-1)
#elif (!REMOVE_HP)&&(!THREE_STAGE)
#define dmaDataSize	(23-1)
#else
	// error
#endif

#if	REMOVE_HP&&THREE_STAGE
#define	dmaCoeffSize	(11-1)
#elif	REMOVE_HP&&(!THREE_STAGE)
#define	dmaCoeffSize	(13-1)
#elif	(!REMOVE_HP)&&THREE_STAGE
#define	dmaCoeffSize	(14-1)
#elif	(!REMOVE_HP)&&(!THREE_STAGE)
#define	dmaCoeffSize	(16-1)
#else
	//	error
#endif



QXrestore:
	
;; dma read the static variables into local memory

	movi	r0, dmaData
	shr	r0, 2 ; convert to word address
	movi	BlockSize, dmaDataSize
	movi	BlockSkip, 0
	movi	DMASize, dmaDataSize
	movi	LocalAddr, (local_data>>2); convert to word
	dmarr	r0
waitd:	bdb	waitd

;; dma read the coeffs variables into local memory

	movi	r0, dmaCoeffs; convert to word address
	shr	r0, 2
	movi	BlockSize, dmaCoeffSize
	movi	DMASize, dmaCoeffSize
	movi	LocalAddr, (local_coeffs>>2); convert to word
	dmarr	r0
waitc:	bdb	waitc

;; dma read the intermediate buffers into local memory

	movi	r0, dmaBuf
	shr	r0, 2 ; convert to word address
	movi	BlockSize, dmaBufSize
	movi	DMASize, dmaBufSize
	movi	LocalAddr,(local_buf>>2); convert to word.
	dmarr	r0
waite:	bdb	waite
	j	r28

;; --------------------------------------------------------------
;; QXInitialise
;  calling: none
;  called by: SUB_QXpander
;  return: r28
;; This routine initialize buffers for QXpander.
;; It is called once at the first time when QXpander is started.
;; It should be called after the QXrestore routine.
;; --------------------------------------------------------------
;; setup the delay ptrs

QXInitialise:

	movi	AGRMod0,0
	movi	AGRMod4,0
	movi	AGRSiz0,0xffff
	movi	AGRSiz4,0xffff
	
	
	movi		AGRAdr0, local_data

	movi		r1,LFBuf
#if	!REMOVE_HP
	mov		r0,a0(20)	;; dummy read to move pointer to left qx delay ptr
#else
	mov		r0,a0(4)	;; dummy read to move pointer to left qx delay ptr
#endif
	movi		r0,RFBuf
	mov		a0(4),r1
	mov		a0(0),r0	 
;; clear data history for filters

	movi		AGRAdr0, local_data
	movi		r1, 0
#if	!REMOVE_HP
	loop		4,clrHighPassData
		mov		a0(4), r1
clrHighPassData:	
#endif
	mov		r0,a0(12)	; dummy read to advance ptr to qfilter history buffer
	loop		NumStages*NumDataPerStage*2,clrQData
		mov		a0(4), r1
clrQData:	
	
	;; clear local memory delay buffers

	movi		AGRAdr4, LFBuf
	nop
	loop		8,clrLFronts
		mov		a4(4), r1
clrLFronts:	
	movi		AGRAdr4, RFBuf
	nop
	loop		8,clrRFronts
		mov		a4(4), r1
clrRFronts:	

	j		r28
	

;; --------------------------------------------------------------
;; QXpander Processing
;; --------------------------------------------------------------
;  calling: none
;  called by: SUB_QXpander
;  return: r28
;;
;; Calling convention:
;; 	in: AGRAdr2 (location to save data)
;; Registers preserved:
;;
;----------------------------------------------------------------
		
QXpander:

	
;; Setup i/o pointer
;; do not trash a0 in the code
			
	movi	AGRAdr0,local_input	; Input pointer


	movi	AGRAdr1, local_data
	movi	AGRAdr4, local_coeffs		;; starting with the scale multipliers

	mupi	r14, 0x007f
	ori	r14, 0xffff
	
	;; Process the data samples.
	loop	256,_QXloop
.if	1	//debug
	;; Apply attenuation to LF and RF
	movhf	r0, a0(2)
	mulf	r16,r0,a4(4)	; LF

	movhf	r0, a0(2)
	mulf	r18,r0,a4(4)	; RF

	;; Apply high pass filter
	
	
	;; rnd only works on the multiplier! so set things up so that
	;; we use the adder portion of the multiplier
#if	!REMOVE_HP
	;;	r20/r21 = HP(LF)
	mulf	r22,i1,a4(4)	; d1*f1		a4-> q1/2

	nop	; MSW - is required

	mov	r15,a4(4)	; r15=q1/2	a4-> 1.0
	madd	r22,r14,a1(-4)	; d2+d1*f1 (LP)
	

	mulf	r10,r15,a1(0)	; q1/2*d1
	madd	r10,r15,a1(0)	; q1*d1

	madd	r10,r22,a4(4)	; q1*d1+LP	a4-> FrontSpread

	mulf	r20,r16,a4(-4)	; LF		a4-> 1.0

	msub	r20,r10,a4(-8)	; (LF) -  (LP + q1*d1) (HP) !!!	a4->f1
	nop	// necessary
	rnd	r20

	mulf	r10,r14,a1(4)	; d1
	madd	r10,r20,a4(0)	; d1 + HP*f1
	
	rnd	a1(-4),r22	; update LP with rounding and saturation
	rnd	a1(8),r10	; update BP with rounding and saturation

	nop	;; MSW this nop is required...	

 	;;	r22/r23 = HP(RF+RS)
	mulf	r12,i1,a4(4)	; d1*f1

	nop	; MSW - is required

	mov	r15,a4(4)	; r15=q1/2	a4-> 1.0
	madd	r12,r14,a1(-4)	; d2 + d1*f1 (LP)


	mulf	r10,r15,a1(0)	; q1/2*d1
	madd	r10,r15,a1(0)	; q1*d1

	madd	r10,r12,a4(4)	; LP+q1*d1	a4 -> FrontSpread

	mulf	r22,r18,a4(-4)	; RF		a4-> 1.0

	msub	r22,r10,a4(-8)	;  (HP)	a4->f1
	nop	// necessary
	rnd	r22

	mulf	r10,r14,a1(4)	; d1
	madd	r10,r22,a4(12)	; d1 + HP*d1 (BP)	advance a4

	rnd	a1(-4),r12	; update LP with rounding and saturation
	rnd	a1(8),r10	; update BP with rounding and saturation


	;; Apply Scott Fix

	mulf	r10,r18,a4(0)	; Front spread
	mulf	r12,r16,a4(4)	; Front spread	a4->sf

	msub	r20,r10,a4(0)	; HP - r18*sf*frontspread
	msub	r22,r12,a4(4)	; HP - r16*sf*frontspread a4->a0
#else 
	mulf	r20,r16,a4(0)	; a4-> spread.  Part of panner complex
	mulf	r22,r18,a4(0)	; a4-> spread. Part of panner complex
#endif

	;; Apply QX delay to LF and RF, mix into LFoutput and RFoutput
	mov	r0,a1(4)	; QX delay
	mov	r1,a1(0)	; LF direct pointer
	mov	AGRSiz7,r0	; 
	mov	AGRAdr7,r1	; LF direct pointer

#if	!REMOVE_HP
	nop
#else
	mulf	r10,r18,a4(0)	; Front Part of Scott fix
#endif
	rnd	a7(4),r16	; store LF with rnd

	mov	r1,AGRAdr7
#if	!REMOVE_HP
	nop
#else
	mulf	r12,r16,a4(4)	; Front 	a4->sf	 part of scott fix
#endif
	mov	a1(4),r1
	mulf	r4,r14,a7(0)	; LFoutput  =delay(LF*FLatten)

	mov	r1,a1(0)	; RF direct pointer
	nop
	mov	AGRAdr7,r1	; RF direct pointer

#if	!REMOVE_HP
	nop
#else
	msub	r20,r10,a4(0)	; HP - r18*sf*frontspread.  Part of scott fix
#endif

	rnd	a7(4),r18	; store RF with rnd

	mov	r1,AGRAdr7
#if	!REMOVE_HP
	nop
#else
	msub	r22,r12,a4(4)	; HP - r16*sf*frontspread.  Part of scott fix
#endif		

	mov	a1(4),r1
	mulf	r6,r14,a7(0)	; RFoutput =delay(RF*FRatten)

	;; now r16/17 and r18/19 are avalible
	
	;; Apply Q Filter, mix into LFoutput and RFoutput

	
	;; at the top of qfilter assume these conditions a4 points to first coeff
	;; this needs to be set up from the highpass coeffs
	;; assume a1 ptrs to history buffer
	
	mulf	r20,r20,a4(0)
	mulf	r22,r22,i4

	loop	(NumStages-1),endqloop
			mov		r17,i4			;;
			msub	r20,r17,a1(0)
			msub	r20,r17,a1(4)	;; a1 ->
			msub	r22,r17,a1(0)
			msub	r22,r17,a1(4)
			mov		r17,i4
			msub	r20,r17,a1(4)
			msub	r22,r17,a1(-12)
			mov		r17,a1(0)
			rnd		a1(8),r20
	
			mov		a1(-4),r17
			mov		r17,a1(0)
			rnd		a1(8),r22
			mov		a1(4),r17
endqloop:	
	mov		r17,i4			;;
	msub	r20,r17,a1(0)
	msub	r20,r17,a1(4)	;; a1 ->
	msub	r22,r17,a1(0)
	msub	r22,r17,a1(4)
#if	REMOVE_HP&&THREE_STAGE
	mov		r17,a4(-40)
#elif	REMOVE_HP&&(!THREE_STAGE)
	mov		r17,a4(-48)
#elif	(!REMOVE_HP)&&THREE_STAGE
	mov		r17,a4(-52)
#elif	(!REMOVE_HP)&&(!THREE_STAGE)
	mov		r17,a4(-60)
#endif
	msub	r20,r17,a1(4)
	msub	r22,r17,a1(-12)
	mov		r17,a1(0)
	rnd		a1(8),r20
	
	mov		a1(-4),r17
	mov		r17,a1(0)
	
	// msw fixed this...
	// j.h was saving the z-1 into the z-2 history for the right side filter.
	// correctly bu the code I've gotten from Richard and Tan lately hasn't been...


	rnd		a1(8),r22

#if 1
	// either have a nop in here so that the r22 value settles into memory or rewind
	// further to the r20 value and do the right addition first.

;;; VERY IMPORTANT use this version of the code not the block below.
;;; the block below doesnot behave correctly it should - msw will have
;;; a look at this.

	mov		a1(-8),r17	; a1-> z-1 of right filter which is added to left channel
	nop;
	madd	r4, r14,a1(-4)	; to r20 position
#if		REMOVE_HP&&THREE_STAGE
	madd	r6, r14,a1(-44)
#elif	REMOVE_HP&&(!THREE_STAGE)
	madd	r6, r14,a1(-60)
#elif	(!REMOVE_HP)&&THREE_STAGE
	madd	r6, r14,a1(-60)
#elif	(!REMOVE_HP)&&(!THREE_STAGE)
	madd	r6, r14,a1(-76)
#else
	error
#endif
#else
	mov	a1(-12),r17	; a1-> z-1 of left filter which is added to right channel
	madd	r6, r14,a1(4)	; to r20 position
#if		REMOVE_HP&&THREE_STAGE
	madd	r4, r14,a1(-48)
#elif	REMOVE_HP&&(!THREE_STAGE)
	madd	r4, r14,a1(-64)
#elif	(!REMOVE_HP)&&THREE_STAGE
	madd	r4, r14,a1(-64)
#elif	(!REMOVE_HP)&&(!THREE_STAGE)
	madd	r4, r14,a1(-80)
#else
	error
#endif



#endif	
;; Update current group with QSurround results

#ifdef	I2S
	rnd		a2(4),r4		;; write LF input
	rnd		a2(4),r6		;; write LR input 
#else
	rndhf		a2(2), r4	;L. middle 16-bit ?
	rndhf		a2(2), r6	;R. to L of next sample
#endif					
.else
	movhf		r4, a0(2)		; 
	movhf		r6, a0(2)		; a0 ->LF
	nop
	nop
#ifdef	I2S
	mov			a2(4), r4
	mov			a2(4), r6
#else
	movhf		a2(2), r4	;L. middle 16-bit ?
	movhf		a2(2), r6	;R. to L of next sample
#endif
.endif	//debug

_QXloop:

	j	r28		; return

;; --------------------------------------------------------------
;; QXsave
;; --------------------------------------------------------------
;  calling: none
;  called by: SUB_QXpander
;  return: r28
;;
;;
;----------------------------------------------------------------
QXsave:
	
;; dma write the intermediate states into DRAM

	movi	r0, dmaData
	shr	r0, 2 ; convert to word address
	movi	BlockSize, dmaDataSize
	movi	DMASize, dmaDataSize
	movi	LocalAddr, (local_data>>2); convert to word?
	dmawr	r0
waits:	bdb	waits

;; dma write the intermediate buffers into DRAM

	movi	r0, dmaBuf
	shr	r0, 2 ; convert to word address
	movi	BlockSize, dmaBufSize
	movi	DMASize, dmaBufSize
	movi	LocalAddr, (local_buf>>2); convert to word?
	dmawr	r0
wait4:	bdb	wait4
	
	j	r28

	
#ifdef	SOFTWARE
	.rdata			//in different section
#else
	.data
#endif	

dmaData:
	.align	4
#if	!REMOVE_HP
	.word	0x00000000	;; d1 left
	.word	0x00000000	;; d2 left
	.word	0x00000000	;; d1 right
	.word	0x00000000	;; d2 right
#endif
	.word	0x0000001c	;; qx delay (7 samples)
	.word	0x00000000	;; qx ptr left (needs to be set)
	.word	0x00000000	; qx ptr right
	.word	0x00000000	;; data buffer (alternates left  right)
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
#if	!THREE_STAGE	
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
	.word	0x00000000
#endif

dmaCoeffs:
	.align	4
#if 0
	.word	0x004026E7	;; lf mult
	.word	0x004026E7	;; rf mult
#else
	.word	0x005FFC87	;; lf mult
	.word	0x005FFC87	;; rf mult
#endif	
#if	!REMOVE_HP
	.word	0x0001d7d2	;; f1 (should be 110 Hz @ 48k)
	.word	0x005A8279	;; q1/2
	.word	0x007FFFFF	; 1.0
#endif
	.word	0x007fffff	;; Spread
	.word	0x007fffff	;; sf (0dB)

filterCoeffs:
	;; default: 44.1K filters (m44both4.bri or m44both3.bri)
#if !THREE_STAGE
	.word	0xFFFFED63	;; a0
	.word	0xFF8A6B6B	;; a1/2
	.word	0x006E3B46	;; a2
	.word	0xFF9AE438	;; a1/2
	.word	0x00607031	;; a2
	.word	0xFFA0CE26	;; a1/2
	.word	0x006AB262	;; a2
	.word	0xFFA62933	;; a1/2
	.word	0x007674F2	;; a2
#else
	.word	0xFFFFDC07	;; a0
	.word	0xFF8AB642	;; a1/2
	.word	0x006DC1C5	;; a2
	.word	0xFF97FB8A	;; a1/2
	.word	0x006687FB	;; a2
	.word	0xFF9A4460	;; a1/2
	.word	0x007559E7	;; a2
#endif	
m44both:
	;; 44.1K filters (m44both4.bri or m44both3.bri)
#if !THREE_STAGE
	.word	0xFFFFED63	;; a0
	.word	0xFF8A6B6B	;; a1/2
	.word	0x006E3B46	;; a2
	.word	0xFF9AE438	;; a1/2
	.word	0x00607031	;; a2
	.word	0xFFA0CE26	;; a1/2
	.word	0x006AB262	;; a2
	.word	0xFFA62933	;; a1/2
	.word	0x007674F2	;; a2
#else
	.word	0xFFFFDC07	;; a0
	.word	0xFF8AB642	;; a1/2
	.word	0x006DC1C5	;; a2
	.word	0xFF97FB8A	;; a1/2
	.word	0x006687FB	;; a2
	.word	0xFF9A4460	;; a1/2
	.word	0x007559E7	;; a2
#endif	
	;; 48K filters (m48both4.bri or m48both3.bri)
m48both:
#if !THREE_STAGE
	.word	0xFFFFF545	;; a0
	.word	0xFFA15E5E	;; a1/2
	.word	0x007674F2	;; a2
	.word	0xFF9D3A0C	;; a1/2
	.word	0x006BC04D	;; a2
	.word	0xFF989590	;; a1/2
	.word	0x0061DCC7	;; a2
	.word	0xFF89F91A	;; a1/2
	.word	0x006ED4F4	;; a2
#else
	.word	0xFFFFE7B6	;; a0
	.word	0xFF89F91A	;; a1/2
	.word	0x006ED4F4	;; a2
	.word	0xFF960027	;; a1/2
	.word	0x0067AE13	;; a2
	.word	0xFF971FEB	;; a1/2
	.word	0x007674F2	;; a2
#endif	
dmaBuf:	.align	2
	.fill	64,4,0
QX_flag:	.align	2
	.word	0x00000000
	
.endif	//QSOUND

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -