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

📄 pcm_soft.c

📁 betaplayer的源码 tcpmp的老版本
💻 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_soft.c 166 2005-01-05 01:31:02Z picard $
 *
 * BetaPlayer Core
 * Copyright (c) 2004 Gabor Kovacs
 *
 ****************************************************************************/

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

static pcm_soft* PCM = NULL;

static INLINE int PCMShift( const audio* Format )
{
	int Bit = 0;
	if (Format->Bits>8) Bit = 1;
	if (Format->Bits>16) Bit = 2;
	if (!(Format->Flags & PCM_PLANES) && Format->Channels==2)
		++Bit;
	return Bit;
}

void PCM_Init()
{
}

void PCM_Done()
{
	pcm_soft* q;
	pcm_soft* p;
	
	for (p=PCM;p;p=q)
	{
		q = p->Next;
		CodeDone(&p->Code);
		Free(p);
	}

	PCM = NULL;
}

#if !defined(ARM) && !defined(SH3) && !defined(MIPS)

void PCM_S16_To_S16_Stereo(pcm_soft* This,const planes DstPtr,const planes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
	int32_t* Src = SrcPtr[0];
	int32_t* Dst = DstPtr[0];
	int32_t* DstEnd = Dst + (DstLength >> 2);

	if (State->Step == 256)
		memcpy(Dst,Src,DstLength);
	else
	{
		int Pos = State->Pos;
		int Step = State->Step;

		while (Dst != DstEnd)
		{
			*(Dst++) = Src[Pos >> 8];
			Pos += Step;
		}
	}
}

void PCM_P32_To_S16_Stereo(pcm_soft* This,const planes DstPtr,const planes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
	int32_t* SrcA = SrcPtr[0];
	int32_t* SrcB = SrcPtr[1];
	int16_t* Dst = DstPtr[0];
	int16_t* DstEnd = Dst + (DstLength >> 1);

	int UpLimit = (1 << This->Src.FracBits) - 1;
	int DownLimit = -(1 << This->Src.FracBits);
	int Shift = This->Src.FracBits - This->Dst.FracBits;

	if (State->Step == 256)
	{
		while (Dst != DstEnd)
		{
			int Left = *(SrcA++);
			int Right = *(SrcB++);

			if (Left > UpLimit) Left = UpLimit;
			if (Left < DownLimit) Left = DownLimit;

			if (Right > UpLimit) Right = UpLimit;
			if (Right < DownLimit) Right = DownLimit;

			Dst[0] = (int16_t)(Left >> Shift);
			Dst[1] = (int16_t)(Right >> Shift);
			Dst += 2;
		}
	}
	else
	{
		int Pos = State->Pos;
		int Step = State->Step;

		while (Dst != DstEnd)
		{
			int Left = SrcA[Pos >> 8];
			int Right = SrcB[Pos >> 8];

			if (Left > UpLimit) Left = UpLimit;
			if (Left < DownLimit) Left = DownLimit;

			if (Right > UpLimit) Right = UpLimit;
			if (Right < DownLimit) Right = DownLimit;

			Dst[0] = (int16_t)(Left >> Shift);
			Dst[1] = (int16_t)(Right >> Shift);
			Dst += 2;
			Pos += Step;
		}
	}
}

void PCMUniversal(pcm_soft* This,const planes DstPtr,const planes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
	uint8_t* Dst[2];
	uint8_t* Src[2];
	uint8_t* DstEnd;
	int DstType = This->DstType;
	int SrcType = This->SrcType;
	int DstStep = 1 << This->DstShift;
	int Pos = State->Pos;
	int Step = State->Step;

	int SrcUnsigned = This->SrcUnsigned;
	int DstUnsigned = This->DstUnsigned;

	int UpLimit = (1 << This->Src.FracBits) - 1;
	int DownLimit = -(1 << This->Src.FracBits);

	int SrcShift = 31 - This->Src.FracBits;
	int DstShift = 31 - This->Dst.FracBits;

	bool_t OnlyLeft = (This->Dst.Flags & PCM_ONLY_LEFT) != 0;
	bool_t OnlyRight = (This->Dst.Flags & PCM_ONLY_RIGHT) != 0;

	bool_t VolumeShift = This->Src.Bits >= 23;
	if (!This->Volume)
		Volume = 256;

	Dst[0] = (uint8_t*) DstPtr[0];
	Dst[1] = (uint8_t*) DstPtr[1];
	Src[0] = (uint8_t*) SrcPtr[0];
	Src[1] = (uint8_t*) SrcPtr[1];

	DstEnd = Dst[0] + DstLength;

	// mono,packed
	// mono,planar
	// stereo,packed
	// stereo,planar

	while (Dst[0] != DstEnd)
	{
		int Left;
		int Right;
	
		if (SrcUnsigned)
			switch (SrcType)
			{
			default:
			case 0:
			case 1:
				Left = Right = ((uint8_t*)Src[0])[Pos >> 8] - SrcUnsigned;
				break;
			case 2:
				Left =  ((uint8_t*)Src[0])[(Pos >> 8)*2] - SrcUnsigned;
				Right = ((uint8_t*)Src[0])[(Pos >> 8)*2+1] - SrcUnsigned;
				break;
			case 3:
				Left =  ((uint8_t*)Src[0])[(Pos >> 8)] - SrcUnsigned;
				Right = ((uint8_t*)Src[1])[(Pos >> 8)] - SrcUnsigned;
				break;

			case 4:
			case 5:
				Left = Right = ((uint16_t*)Src[0])[Pos >> 8] - SrcUnsigned;
				break;
			case 6:
				Left =  ((uint16_t*)Src[0])[(Pos >> 8)*2] - SrcUnsigned;
				Right = ((uint16_t*)Src[0])[(Pos >> 8)*2+1] - SrcUnsigned;
				break;
			case 7:
				Left =  ((uint16_t*)Src[0])[(Pos >> 8)] - SrcUnsigned;
				Right = ((uint16_t*)Src[1])[(Pos >> 8)] - SrcUnsigned;
				break;

			case 8:
			case 9:
				Left = Right = ((uint32_t*)Src[0])[Pos >> 8] - SrcUnsigned;
				break;
			case 10:
				Left =  ((uint32_t*)Src[0])[(Pos >> 8)*2] - SrcUnsigned;
				Right = ((uint32_t*)Src[0])[(Pos >> 8)*2+1] - SrcUnsigned;
				break;
			case 11:
				Left =  ((uint32_t*)Src[0])[(Pos >> 8)] - SrcUnsigned;
				Right = ((uint32_t*)Src[1])[(Pos >> 8)] - SrcUnsigned;
				break;
			}
		else
			switch (SrcType)
			{
			default:
			case 0:
			case 1:
				Left = Right = ((int8_t*)Src[0])[Pos >> 8];
				break;
			case 2:
				Left =  ((int8_t*)Src[0])[(Pos >> 8)*2];
				Right = ((int8_t*)Src[0])[(Pos >> 8)*2+1];
				break;
			case 3:
				Left =  ((int8_t*)Src[0])[(Pos >> 8)];
				Right = ((int8_t*)Src[1])[(Pos >> 8)];
				break;

			case 4:
			case 5:
				Left = Right = ((int16_t*)Src[0])[Pos >> 8];
				break;
			case 6:
				Left =  ((int16_t*)Src[0])[(Pos >> 8)*2];
				Right = ((int16_t*)Src[0])[(Pos >> 8)*2+1];
				break;
			case 7:
				Left =  ((int16_t*)Src[0])[(Pos >> 8)];
				Right = ((int16_t*)Src[1])[(Pos >> 8)];
				break;

			case 8:
			case 9:
				Left = Right = ((int32_t*)Src[0])[Pos >> 8];
				break;
			case 10:
				Left =  ((int32_t*)Src[0])[(Pos >> 8)*2];
				Right = ((int32_t*)Src[0])[(Pos >> 8)*2+1];
				break;
			case 11:
				Left =  ((int32_t*)Src[0])[(Pos >> 8)];
				Right = ((int32_t*)Src[1])[(Pos >> 8)];
				break;
			}

		if (Volume != 256)
		{
			if (VolumeShift)
			{
				Left = (Left >> 8) * Volume;
				Right = (Right >> 8) * Volume;
			}
			else
			{
				Left = (Left * Volume) >> 8;
				Right = (Right * Volume) >> 8;
			}
		}

		if (Left > UpLimit) Left = UpLimit;
		if (Left < DownLimit) Left = DownLimit;

		if (Right > UpLimit) Right = UpLimit;
		if (Right < DownLimit) Right = DownLimit;

		Left <<= SrcShift;
		Right <<= SrcShift;

		Left >>= DstShift;
		Right >>= DstShift;

		if (OnlyLeft)
			Right = Left;
		if (OnlyRight)
			Left = Right;

		switch (DstType)
		{
		default:
		case 0:
		case 1:
			((int8_t*)Dst[0])[0] = (int8_t)(((Left + Right) >> 1) + DstUnsigned);
			break;
		case 2:
			((int8_t*)Dst[0])[0] = (int8_t)(Left + DstUnsigned);
			((int8_t*)Dst[0])[1] = (int8_t)(Right + DstUnsigned);
			break;
		case 3:
			((int8_t*)Dst[0])[0] = (int8_t)(Left + DstUnsigned);
			((int8_t*)Dst[1])[0] = (int8_t)(Right + DstUnsigned);
			break;

		case 4:
		case 5:
			((int16_t*)Dst[0])[0] = (int16_t)(((Left + Right) >> 1) + DstUnsigned);
			break;
		case 6:
			((int16_t*)Dst[0])[0] = (int16_t)(Left + DstUnsigned);
			((int16_t*)Dst[0])[1] = (int16_t)(Right + DstUnsigned);
			break;
		case 7:
			((int16_t*)Dst[0])[0] = (int16_t)(Left + DstUnsigned);
			((int16_t*)Dst[1])[0] = (int16_t)(Right + DstUnsigned);
			break;

		case 8:
		case 9:
			((int32_t*)Dst[0])[0] = ((Left+Right) >> 1) + DstUnsigned;
			break;
		case 10:
			((int32_t*)Dst[0])[0] = Left + DstUnsigned;
			((int32_t*)Dst[0])[1] = Right + DstUnsigned;
			break;
		case 11:
			((int32_t*)Dst[0])[0] = Left + DstUnsigned;
			((int32_t*)Dst[1])[0] = Right + DstUnsigned;
			break;
		}

		Pos += Step;
		Dst[0] += DstStep;
		Dst[1] += DstStep;
	}
}

static int UniversalType(const audio* Format)
{
	int Type = (Format->Channels - 1)*2;
	if (Format->Flags & PCM_PLANES) Type |= 1;
	if (Format->Bits>8) Type += 4;
	if (Format->Bits>16) Type += 4;
	return Type;
}
	
#endif

void* PCMCreate( const audio* DstFormat, const audio* SrcFormat, bool_t Dither, bool_t Volume )
{
	pcm_soft* p = PCM;
	if (p)
		PCM = p->Next;
	else
	{
		p = (pcm_soft*) CAlloc(sizeof(pcm_soft),1);
		if (!p)
			return NULL;

		CodeInit(&p->Code);
	}

	if (!EqAudio(&p->Dst,DstFormat) ||
		!EqAudio(&p->Src,SrcFormat) ||
		p->Volume != Volume || 
		p->Dither != Dither)
	{
		p->Entry = NULL;
		p->Dst = *DstFormat;
		p->Src = *SrcFormat;
		p->Dither = Dither;
		p->Volume = Volume;

		// only PCM streams are supported
		if (p->Dst.Format==AUDIOFMT_PCM && p->Src.Format==AUDIOFMT_PCM) 
		{
			p->SrcShift = PCMShift(&p->Src);
			p->DstShift = PCMShift(&p->Dst);

			p->SrcUnsigned = (p->Src.Flags & PCM_UNSIGNED) ? (1 << (p->Src.Bits-1)):0;
			p->DstUnsigned = (p->Dst.Flags & PCM_UNSIGNED) ? (1 << (p->Dst.Bits-1)):0;

			p->UseLeft = (p->Dst.Flags & PCM_ONLY_RIGHT)==0 || (p->Src.Channels <= 1);
			p->UseRight = (p->Dst.Flags & PCM_ONLY_LEFT)==0 && (p->Src.Channels > 1);
			p->SrcChannels = (p->UseLeft && p->UseRight) ? 2:1;

			p->Clip = (p->Src.Bits - p->Src.FracBits) - (p->Dst.Bits - p->Dst.FracBits);
			p->Stereo = p->SrcChannels > 1 && p->Dst.Channels > 1;
			p->Join = !p->Stereo && (p->SrcChannels > 1);
			
			p->Shift = p->Dst.FracBits - p->Src.FracBits - p->Join;
			p->ActualDither = !p->Volume && p->Dither && ((p->Clip>0) || (p->Shift<0));
			
			p->Limit2 = p->Src.Bits + p->Join - p->Clip - 1;

			if (p->Volume && p->Src.Bits < 23)
			{
				p->Shift -= 8;
				p->Limit2 += 8;
			}

			p->MaxLimit = (1 << p->Limit2) - 1;
			p->MinLimit = -(1 << p->Limit2);

			p->State.Speed = -1;
			p->State.Step = 256;

#if defined(ARM) || defined(SH3) || defined(MIPS)
			CodeStart(&p->Code);
			PCMCompile(p);
			CodeBuild(&p->Code);
			if (p->Code.Size)
				p->Entry = (pcmsoftentry)p->Code.Code;
#else
			p->SrcType = UniversalType(&p->Src);
			p->DstType = UniversalType(&p->Dst);
			p->Entry = PCMUniversal;

			if (!p->Volume && !p->DstUnsigned && p->DstType==6 &&	
				!(p->Dst.Flags & (PCM_ONLY_LEFT|PCM_ONLY_RIGHT)))
			{
				//PCM_P32_To_S16_Stereo
				if (p->Src.FracBits >= p->Dst.FracBits && !p->SrcUnsigned && p->SrcType==11)
					p->Entry = PCM_P32_To_S16_Stereo;
				else
				if (p->Src.FracBits == p->Dst.FracBits && !p->SrcUnsigned && p->SrcType==6)
					p->Entry = PCM_S16_To_S16_Stereo;
			}
#endif
		}
	}

	if (!p->Entry)
	{
		p->Next = PCM;
		PCM = p;
		p = NULL;
	}

	PCMReset(p);
	return p;
}

void PCMRelease(void* Handle)
{
	pcm_soft* p = (pcm_soft*) Handle;
	if (p)
	{
		p->Next = PCM;
		PCM = p;
	}
}

void PCMConvert( void* Handle, const planes Dst, const planes Src, int* DstLength, int* SrcLength, int Speed, int Volume )
{
	int SrcSamples;
	int DstSamples;
	int AvailSamples;
	pcm_soft* p = (pcm_soft*) Handle;

	if (!p) return;

	SrcSamples = *SrcLength >> p->SrcShift;
	DstSamples = *DstLength >> p->DstShift;

	if (p->State.Speed != Speed)
	{
		p->State.Speed = Speed;
		p->State.Step = Scale(Speed,p->Src.SampleRate,p->Dst.SampleRate*256);
		if (p->State.Step<=0)
			p->State.Step = 256;
	}

	if (p->State.Step != 256)
	{
		AvailSamples = ((SrcSamples << 8) - p->State.Pos + p->State.Step - 1) / p->State.Step;
		if (DstSamples > AvailSamples)
			DstSamples = AvailSamples;

		AvailSamples = (p->State.Pos + DstSamples * p->State.Step) >> 8;
		if (SrcSamples > AvailSamples)
			SrcSamples = AvailSamples;
	}
	else
	{
		if (DstSamples > SrcSamples)
			DstSamples = SrcSamples;
		SrcSamples = DstSamples;
	}
	
	*SrcLength = SrcSamples << p->SrcShift;
	*DstLength = DstSamples << p->DstShift;
	
	if (DstSamples)
		p->Entry(p,Dst,Src,*DstLength,&p->State,Volume);

	p->State.Pos += (DstSamples * p->State.Step) - (SrcSamples << 8);
}

void PCMReset( void* Handle )
{
	pcm_soft* p = (pcm_soft*) Handle;
	if (p)
	{
		p->State.Pos = 0;
		p->State.Dither[0] = 0;
		p->State.Dither[1] = 0;
	}
}

⌨️ 快捷键说明

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