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

📄 law.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_arm.c 22 2004-07-19 16:23:22Z picard $
 *
 * BetaPlayer Core
 * Copyright (c) 2004 Gabor Kovacs
 *
 ****************************************************************************/

#include "../stdafx.h"
#include "law.h"

#define LAW_INPUT	0x100
#define LAW_OUTPUT	0x101

const datadef LawParams[] = 
{
	{ LAW_ID,		TYPE_CLASS },
	{ LAW_INPUT,	TYPE_PACKET, DF_INPUT, PACKET_AUDIO },
	{ LAW_OUTPUT,	TYPE_PIN, DF_OUTPUT, PACKET_AUDIO },

	DATADEF_END
};

typedef struct law
{
	node VMT;

	int Id;
	int Format;

	audio InputFormat;
	audio OutputFormat;
	pin Output;

	int BufSize;
	int Total;
	packet Packet;

	int16_t Table[256];

} law;

static int SetFormat( law* p, const audio* Format )
{
	memset(&p->InputFormat,0,sizeof(p->InputFormat));
	Free(p->Packet.Data[0]);
	p->Packet.Data[0] = NULL;
	p->BufSize = 0;

	if (Format)
	{
		if (Format->Format != p->Format || Format->Bits != 8)
			return ERR_INVALID_DATA;

		p->InputFormat = *Format;

		p->OutputFormat.Flags = 0;
		p->OutputFormat.Format = AUDIOFMT_PCM;
		p->OutputFormat.Bits = 16;
		p->OutputFormat.FracBits = 15;
		p->OutputFormat.SampleRate = p->InputFormat.SampleRate;
		p->OutputFormat.Channels = p->InputFormat.Channels;
		p->Total = 0;
	}
	return ERR_NONE;
}

static int Decode( law* p, const packet* Packet )
{
	uint8_t* se;
	uint8_t* s;
	int16_t* d;

	p->Packet.CurrTime = Packet->CurrTime;
	p->Packet.DropLevel = Packet->DropLevel;
	p->Packet.Length = Packet->Length*2;
	p->Packet.RefTime = Packet->RefTime;

	if (p->InputFormat.Channels>1)
		p->Total += Packet->Length >> 1;
	else
		p->Total += Packet->Length;

	if (p->BufSize < p->Packet.Length)
	{
		p->Packet.Data[0] = ReAlloc(p->Packet.Data[0],p->Packet.Length);
		if (!p->Packet.Data[0])
		{
			p->BufSize = 0;
			return ERR_OUT_OF_MEMORY;
		}
		p->BufSize = p->Packet.Length;
	}

	s = (uint8_t*)Packet->Data[0];
	se = s + Packet->Length;
	d = (int16_t*)p->Packet.Data[0];
	for (;s!=se;++s,++d)
		*d = p->Table[*s];

	return p->Output.Node->Set(p->Output.Node,p->Output.No,&p->Packet,sizeof(packet));
}

static int Enum( law* p, int No, datadef* Param )
{
	return NodeEnumType(&No,Param,NodeParams,FlowParams,LawParams,NULL);
}

static int Get( law* p, int No, void* Data, int Size )
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case NODE_ID: GETVALUE(p->Id,int); break;
	case LAW_INPUT | PACKET_FORMAT: GETVALUE(p->InputFormat,audio); break;
	case LAW_OUTPUT | PACKET_FORMAT: GETVALUE(p->OutputFormat,audio); break;
	case LAW_OUTPUT: GETVALUE(p->Output,pin); break;
	case FLOW_TOTAL:GETVALUE(p->Total,int); break;
	}
	return Result;
}

static int Set( law* p, int No, const void* Data, int Size )
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case LAW_INPUT | PACKET_FORMAT:
		if (!Size || Size == sizeof(audio))
		{
			if (!Size) Data = NULL;
			Result = SetFormat(p,(const audio*)Data);
		}
		break;

	case LAW_INPUT:
		if (Size == sizeof(packet))
			Result = Decode(p,(const packet*)Data);
		break;

	case LAW_OUTPUT:
		if (Size == sizeof(pin))
			Result = NodeSetPin(&p->Output,(pin*)Data,&p->OutputFormat,sizeof(audio));
		break;

	case FLOW_TOTAL: SETVALUE(p->Total,int,ERR_NONE); break;
	}
	return Result;
}

static law ALAW;
static law MULAW;

/* from g711.c by SUN microsystems (unrestricted use) */

#define	SIGN_BIT	(0x80)		/* Sign bit for a A-law byte. */
#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
#define	NSEGS		(8)		/* Number of A-law segments. */
#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
#define	SEG_MASK	(0x70)		/* Segment field mask. */

#define	BIAS		(0x84)		/* Bias for linear code. */

/*
 * alaw2linear() - Convert an A-law value to 16-bit linear PCM
 *
 */
static int alaw2linear(int a_val)
{
	int		t;
	int		seg;

	a_val ^= 0x55;

	t = (a_val & QUANT_MASK) << 4;
	seg = (a_val & SEG_MASK) >> SEG_SHIFT;
	switch (seg) {
	case 0:
		t += 8;
		break;
	case 1:
		t += 0x108;
		break;
	default:
		t += 0x108;
		t <<= seg - 1;
	}
	return ((a_val & SIGN_BIT) ? t : -t);
}

static int ulaw2linear(int u_val)
{
	int		t;

	/* Complement to obtain normal u-law value. */
	u_val ^= 0xFF;

	/*
	 * Extract and bias the quantization bits. Then
	 * shift up by the segment number and subtract out the bias.
	 */
	t = ((u_val & QUANT_MASK) << 3) + BIAS;
	t <<= (u_val & SEG_MASK) >> SEG_SHIFT;

	return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}

void Law_Init()
{
	int n;
	law* p;

	p = &ALAW;
	NodeFill(&p->VMT,sizeof(law),(nodeenum)Enum,(nodeget)Get,(nodeset)Set);
	p->Id = ALAW_ID;
	p->Format = AUDIOFMT_ALAW;
	for (n=0;n<256;++n)
		p->Table[n] = (int16_t)alaw2linear(n);
	NodeRegister(&p->VMT,PRI_DEFAULT);

	p = &MULAW;
	NodeFill(&p->VMT,sizeof(law),(nodeenum)Enum,(nodeget)Get,(nodeset)Set);
	p->Id = MULAW_MS_ID;
	p->Format = AUDIOFMT_MULAW;
	for (n=0;n<256;++n)
		p->Table[n] = (int16_t)ulaw2linear(n);
	NodeRegister(&p->VMT,PRI_DEFAULT);
}

void Law_Done()
{
	NodeUnRegister(&ALAW.VMT);
	NodeUnRegister(&MULAW.VMT);
}



⌨️ 快捷键说明

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