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

📄 pcm_arm.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
字号:
/*****************************************************************************
 *
 * This program is free software ; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: pcm_arm.c 304 2005-10-20 11:02:59Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/

#include "../common.h"
#include "../dyncode/dyncode.h"
#include "pcm_soft.h"

#if defined(ARM)

typedef struct stack
{
	int StackFrame[STACKFRAME];

	//void* this   R0
	//plane Dst    R1
	//plane Src    R2
	//int DstLength R3
	pcmstate* State;
	int Volume;

} stack;

// R0,R1 dither 
// R2,R3 value
// R4 Min
// R5 Max
// R6 tmp
// R7 Step
// R8 Pos
// R9 SrcLeft
// R10 SrcRight
// R11 DstLeft
// R12 DstRight
// R14 DstLeftEnd

void PCMLoop(pcm_soft* p,bool_t Speed)
{
	dyninst* Loop;
	reg Left;
	reg Right;

	Loop = Label(1);

	Left = R2;
	if (p->UseLeft)
		Right = R3;
	else
		Right = R2;

	if (Speed)
	{
		I3S(MOV,R3,NONE,R8,LSR,8);

		switch (p->Src.Bits)
		{
		case 8:
			if (p->SrcUnsigned)	
			{
				if (p->UseLeft)
				{
					Byte();	I3S(LDR,Left,R9,R3,LSL,p->SrcShift);
				}
				if (p->UseRight)
				{
					Byte();	I3S(LDR,Right,R10,R3,LSL,p->SrcShift);
				}
			}
			else
			{
				I3S(MOV,R3,NONE,R3,LSL,p->SrcShift);
				if (p->UseLeft)
				{
					SByte(); I3(LDR,Left,R9,R3);
				}
				if (p->UseRight)
				{
					SByte(); I3(LDR,Right,R10,R3);
				}
			}
			break;

		case 16:
			I3S(MOV,R3,NONE,R3,LSL,p->SrcShift);
			if (p->UseLeft)
			{
				if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
				I3(LDR,Left,R9,R3);
				if (p->SrcSwap)
				{
					I3S(MOV,R6,NONE,Left,LSL,24);
					I3S(MOV,Left,NONE,Left,LSR,8);
					if (p->SrcUnsigned)
						I3S(ORR,Left,Left,R6,LSR,16);
					else
						I3S(ORR,Left,Left,R6,ASR,16);
				}
			}
			if (p->UseRight)
			{
				if (p->SrcUnsigned || p->SrcSwap) Half();	else SHalf();
				I3(LDR,Right,R10,R3);
				if (p->SrcSwap)
				{
					I3S(MOV,R6,NONE,Right,LSL,24);
					I3S(MOV,Right,NONE,Right,LSR,8);
					if (p->SrcUnsigned)
						I3S(ORR,Right,Right,R6,LSR,16);
					else
						I3S(ORR,Right,Right,R6,ASR,16);
				}
			}
			break;

		case 32:
			if (p->UseLeft)
				I3S(LDR,Left,R9,R3,LSL,p->SrcShift);
			if (p->UseRight)
				I3S(LDR,Right,R10,R3,LSL,p->SrcShift);
			break;
		}
		I3(ADD,R8,R8,R7);
	}
	else
	{
		switch (p->Src.Bits)
		{
		case 8:
			if (p->UseLeft)
			{
				if (p->SrcUnsigned)	Byte();	else SByte();
				I2C(LDR_POST,Left,R9,1<<p->SrcShift);
			}
			if (p->UseRight)
			{
				if (p->SrcUnsigned)	Byte();	else SByte();
				I2C(LDR_POST,Right,R10,1<<p->SrcShift);
			}
			break;

		case 16:
			if (p->UseLeft)
			{
				if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
				I2C(LDR_POST,Left,R9,1<<p->SrcShift);
				if (p->SrcSwap)
				{
					I3S(MOV,R6,NONE,Left,LSL,24);
					I3S(MOV,Left,NONE,Left,LSR,8);
					if (p->SrcUnsigned)
						I3S(ORR,Left,Left,R6,LSR,16);
					else
						I3S(ORR,Left,Left,R6,ASR,16);
				}
			}
			if (p->UseRight)
			{
				if (p->SrcUnsigned || p->SrcSwap) Half(); else SHalf();
				I2C(LDR_POST,Right,R10,1<<p->SrcShift);
				if (p->SrcSwap)
				{
					I3S(MOV,R6,NONE,Right,LSL,24);
					I3S(MOV,Right,NONE,Right,LSR,8);
					if (p->SrcUnsigned)
						I3S(ORR,Right,Right,R6,LSR,16);
					else
						I3S(ORR,Right,Right,R6,ASR,16);
				}
			}
			break;

		case 32:
			if (p->UseLeft)
				I2C(LDR_POST,Left,R9,1<<p->SrcShift);
			if (p->UseRight)
				I2C(LDR_POST,Right,R10,1<<p->SrcShift);
			break;
		}
	}

	if (p->SrcUnsigned) 
	{
		I2C(SUB,R2,R2,p->SrcUnsigned);
		if (p->SrcChannels>1)
			I2C(SUB,R3,R3,p->SrcUnsigned);
	}

	if (p->Stereo)
	{
		if ((p->Src.Flags ^ p->Dst.Flags) & PCM_SWAPPEDSTEREO)
		{
			Left = R3;
			Right = R2;
		}
		else
		{
			Left = R2;
			Right = R3;
		}
	}
	else
	{
		if (p->Join)
			I3(ADD,R2,R2,R3);
		Right = Left = R2;
	}

	if (p->ActualDither)
	{
		I3(ADD,R2,R2,R0);
		I3(MOV,R0,NONE,R2);
		if (p->Stereo) 
		{
			I3(ADD,R3,R3,R1);
			I3(MOV,R1,NONE,R3);
		}
	}

	if (p->UseVolume)
	{
		if (p->Src.Bits >= 23)
			I3S(MOV,R2,NONE,R2,ASR,8);
		I3(MUL,R2,R0,R2);

		if (p->Stereo)
		{
			if (p->Src.Bits >= 23)
				I3S(MOV,R3,NONE,R3,ASR,8);
			I3(MUL,R3,R0,R3);
		}
	}

	if (p->Clip>0)
	{
		I3(CMP,NONE,R2,R4);
		C(LT); I3(MOV,R2,NONE,R4);
		I3(CMP,NONE,R2,R5);
		C(GT); I3(MOV,R2,NONE,R5);

		if (p->Stereo)
		{
			I3(CMP,NONE,R3,R4);
			C(LT); I3(MOV,R3,NONE,R4);
			I3(CMP,NONE,R3,R5);
			C(GT); I3(MOV,R3,NONE,R5);
		}
	}

	if (p->Shift)
	{
		I3S(MOV,R2,NONE,R2,ASR,-p->Shift);
		if (p->Stereo) I3S(MOV,R3,NONE,R3,ASR,-p->Shift);
	}

#ifdef TARGET_PALMOS
	if (p->LifeDriveFix)
	{
		I3S(ADD,R6,R2,R1,LSL,1);
		I3S(CMP,NONE,R6,R1,LSL,2);
		C(LS); I2C(ORR,R2,R2,R0);
		if (p->Stereo)
		{
			I3S(ADD,R6,R3,R1,LSL,1);
			I3S(CMP,NONE,R6,R1,LSL,2);
			C(LS); I3(ORR,R3,R3,R0);
		}
	}
#endif

	if (p->ActualDither)
	{
		I3S(SUB,R0,R0,R2,ASR,p->Shift);
		if (p->Stereo) I3S(SUB,R1,R1,R3,ASR,p->Shift);
	}

	if (p->DstUnsigned) 
	{
		I2C(ADD,Left,Left,p->DstUnsigned);
		if (Left != Right)
			I2C(ADD,Right,Right,p->DstUnsigned);
	}

	switch (p->Dst.Bits)
	{
	case 8:
		Byte(); I2C(STR_POST,Left,R11,1<<p->DstShift);
		if (p->Dst.Channels>1)
		{
			Byte(); I2C(STR_POST,Right,R12,1<<p->DstShift);
		}
		break;

	case 16:
		Half(); I2C(STR_POST,Left,R11,1<<p->DstShift);
		if (p->Dst.Channels>1)
		{
			Half(); I2C(STR_POST,Right,R12,1<<p->DstShift);
		}
		break;

	case 32:
		I2C(STR_POST,Left,R11,1<<p->DstShift);
		if (p->Dst.Channels>1)
			I2C(STR_POST,Right,R12,1<<p->DstShift);
		break;
	}

	I3(CMP,NONE,R11,R14);
	I0P(B,NE,Loop);
	
	if (p->ActualDither)
	{
		I2C(LDR,R4,SP,OFS(stack,State));
		I2C(STR,R0,R4,OFS(pcmstate,Dither[0]));
		I2C(STR,R1,R4,OFS(pcmstate,Dither[1]));
	}

	CodeEnd();
}

void PCMCompile(pcm_soft* p)
{
	dyninst* Speed;
	dyninst* Min = NULL;
	dyninst* Max = NULL;

	CodeBegin();

	// dst pointers
	I2C(LDR,R11,R1,0);
	if (p->Dst.Channels > 1)
	{
		if (p->Dst.Flags & PCM_PLANES)
			I2C(LDR,R12,R1,4);
		else
			I2C(ADD,R12,R11,1<<(p->DstShift-1));
	}
	I3(ADD,R14,R11,R3); // dstend

	// src pointers
	I2C(LDR,R9,R2,0);
	if (p->Src.Channels > 1)
	{
		if (p->Src.Flags & PCM_PLANES)
			I2C(LDR,R10,R2,4);
		else
			I2C(ADD,R10,R9,p->Src.Bits>>3);
	}

	I2C(LDR,R4,SP,OFS(stack,State));

	I2C(LDR,R7,R4,OFS(pcmstate,Step));
	I2C(LDR,R8,R4,OFS(pcmstate,Pos));

#ifdef TARGET_PALMOS
	if (p->LifeDriveFix)
	{
		I2C(LDR,R1,SP,OFS(stack,Volume));
		I2C(MOV,R0,NONE,63);
		I2C(CMP,NONE,R1,25);
		C(GT); I2C(MOV,R0,NONE,31);
		I2C(CMP,NONE,R1,50);
		C(GT); I2C(MOV,R0,NONE,15);
		I2C(CMP,NONE,R1,100);
		C(GT); I2C(MOV,R0,NONE,7);
		I2C(CMP,NONE,R1,200);
		C(GT); I2C(MOV,R0,NONE,3);
		I2C(ADD,R1,R0,1);
	}
#endif

	if (p->UseVolume)
		I2C(LDR,R0,SP,OFS(stack,Volume));

	if (p->ActualDither)
	{
		I2C(LDR,R0,R4,OFS(pcmstate,Dither[0]));
		I2C(LDR,R1,R4,OFS(pcmstate,Dither[1]));
	}

	if (p->Clip>0)
	{
		Min = InstCreate32(p->MinLimit,NONE,NONE,NONE,0,0);
		Max = InstCreate32(p->MaxLimit,NONE,NONE,NONE,0,0);

		I1P(LDR,R4,Min,0);
		I1P(LDR,R5,Max,0);
	}

	Speed = Label(0);
	I2C(CMP,NONE,R7,256);
	I0P(B,NE,Speed);

	PCMLoop(p,0);

	InstPost(Speed);

	PCMLoop(p,1);

	if (Min) InstPost(Min);
	if (Max) InstPost(Max);
}


#endif

⌨️ 快捷键说明

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