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

📄 pcmtran.cpp

📁 基于mips架构的ATI-XILLEON 226的mp3解码程序
💻 CPP
字号:
#include <stdio.h>

#include <stdlib.h>

#include <string.h>



#include "pcmtran.h"



#define MAKETAG(a, b, c, d) (((((long)a)%256)<<24) | ((((long)b)%256)<<16) | ((((long)c)%256)<<8) | ((((long)d)%256)<<0))



typedef struct tagPcmTranCtrl

{

	unsigned long tag ;

	

	int s_c ;		/* source channels */

	int s_sw ;		/* source sample width */

	int s_sr ;		/* source sample rate (hz) */



	int d_c ;		/* dest channels */

	int d_sw ;		/* dest sample width */

	int d_sr ;		/* dest sample rate (hz) */

	

	int s_max_len ;	/* source max input length */

	

	unsigned char *w_b0 ;	/* work buffer 0 */

	unsigned char *w_b1 ;	/* work buffer 1 */

	

} PcmTranCtrl_t, *pPcmTranCtrl_t ;



static unsigned long _tag = (unsigned long) MAKETAG('P', 'T', 'R', 'A') ;



/* sample rate convert */

static int sr_conv(unsigned char *inbuf0, unsigned char *inbuf1, int width, int channel, unsigned char *outbuf, int level) ;



/* sample width convert */

static int sw_conv(unsigned char *inbuf, int source_width, int channel, int dest_width, unsigned char *outbuf) ;



unsigned long pcm_transform_open(int source_channels, int source_sample_width, int source_samples_rate, int dest_channels, int dest_sample_width, int dest_samples_rate, int max_input_len)

{

	unsigned long result = 0 ;

	PcmTranCtrl_t *p ;

	int err = 1 ;



	if (

		(source_channels == 1 || source_channels == 2)

		&& (source_sample_width == 8 || source_sample_width == 16 || source_sample_width == 24 || source_sample_width == 32)

		&& (source_samples_rate == 11025 || source_samples_rate == 22050 || source_samples_rate == 44100)

		&& (dest_channels == 1 || dest_channels == 2)

		&& (dest_sample_width == 8 || dest_sample_width == 16 || dest_sample_width == 24 || dest_sample_width == 32)

		&& (dest_samples_rate == 11025 || dest_samples_rate == 22050 || dest_samples_rate == 44100)

		

		&& (!(source_channels == dest_channels && source_sample_width == dest_sample_width && source_samples_rate == dest_samples_rate))

		

		&& max_input_len > 0

		)

	{

		p = (PcmTranCtrl_t *)malloc(sizeof(PcmTranCtrl_t)) ;

		if (p)

		{

			size_t size ;

			

			memset(p, 0x00, sizeof(PcmTranCtrl_t)) ;

			p->tag = _tag ;

			p->s_c = source_channels ;

			p->s_sw = source_sample_width ;

			p->s_sr = source_samples_rate ;

			p->d_c = dest_channels ;

			p->d_sw = dest_sample_width ;

			p->d_sr = dest_samples_rate ;

			p->s_max_len = max_input_len ;

			

			size = (size_t)((p->s_c>p->d_c)?p->s_c:p->d_c) ;

			size *= (size_t)(((p->s_sw>p->d_sw)?p->s_sw:p->d_sw)/8) ;

			size *= (size_t)(max_input_len/(p->s_c*(p->s_sw/8))+1) ;

			if (size > 0

				&& (p->w_b0 = (unsigned char *)malloc(size))

				&& (p->w_b1 = (unsigned char *)malloc(size))

				)

			{

				err = 0 ;

			}

		}

	}



	if (err)

	{

		if (p

			&& p->w_b0

			)

			free(p->w_b0) ;

		if (p

			&& p->w_b1

			)

			free(p->w_b1) ;

		if (p)

			free(p) ;			

	}

	else

	{

		result = (unsigned long)p ;

	}

	

	return (result) ;

}



int pcm_transform_close(unsigned long handle)

{

	int result = -1 ;

	PcmTranCtrl_t *p ; 

	

	p = (PcmTranCtrl_t *)handle ;

	if (p

		&& p->tag == _tag

		)

	{

		if (p->w_b0)

			free(p->w_b0) ;

		if (p->w_b1)

			free(p->w_b1) ;

		free(p) ;

		result = 0 ;

	}

	

	return (result) ;

}



int pcm_transform(unsigned long handle, char *inbuf, int inbuf_len, char **outbuf, int *output_len)

{

	int result = PCMTRAN_ERR_GENERAL ;

	PcmTranCtrl_t *p ; 

	

		

	p = (PcmTranCtrl_t *)handle ;

	if (p	&& p->tag == _tag

		&& inbuf

		&& *outbuf)

	{

			int i, j ;

			int _c = p->s_c ;		/* current channels */

			int _sw = p->s_sw ;		/* current sample width */

			int _sr = p->s_sr ;		/* current sample rate */

			int _sn = inbuf_len/(_c*(_sw/8)) ;	/* current samples number */

			

			unsigned char *s_b ;	/* source buffer */

			unsigned char *d_b ;	/* dest buffer */

			

			int len = 0 ;

			int _s_sn = _sn ;		/* source samples number used to convert */

			

			if (!(pcm_transform_getdestsize(handle, inbuf_len, &len) == 0

					&& len <= *output_len

					&& inbuf_len <= p->s_max_len

					)

				)

				goto done ;

				

			/* channel convert */

			s_b = (unsigned char *)inbuf ;

			d_b = (unsigned char *)p->w_b0 ;

			if (p->s_c == 1

				&& p->d_c == 2

				)

			{

				int w = _sw/8 ;

				

				for (i=0, j=0; i<_sn; i++)

				{

					memcpy(d_b+j, s_b+i*w, w) ;

					j += w ;

					memcpy(d_b+j, s_b+i*w, w) ;

					j += w ;

				}

				_c = p->d_c ;

			}

			else

			if (p->s_c == 2

				&& p->d_c == 1

				)

			{

				int w = _sw/8 ;

				int off = 0 ; /* int off = 0, left channel; int off = w, right channel */

				

				for (i=0, j=0; i<_sn; i++)

				{

					memcpy(d_b+j, s_b+i*2*w+off, w) ;

					j += w ;

				}

				_c = p->d_c ;

			}

			else

			{

				result = PCMTRAN_ERR_SAMCHAN ;

				goto done ;	

			}

			

			/* sampleRate convert */

			s_b = (unsigned char *)p->w_b0 ;

			d_b = (unsigned char *)p->w_b1 ;

			if (p->s_sr == 11025)

			{

				int w = _sw/8 ;

				unsigned char buf[2*4*4] ;

				

				if (p->d_sr == 22050)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						int r ;

						unsigned char *p0, *p1 ;

						

						p0 = s_b+i*w*_c ;

						p1 = s_b+(i+1)*w*_c ;

						if (i+1 >= _sn)

							p1 = p0 ;

						

						/* get the prev sample (one or two) */

						memcpy(d_b+j, p0, w*_c) ;

						j += (w*_c) ;

						

						r = sr_conv(p0, p1, w, _c, buf, 1) ;

						if (r > 0)

						{

							memcpy(d_b+j, buf, r) ;

							j += r ;

						}

						else

						{

							memcpy(d_b+j, p0, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn/2 ;

				}

				else

				if (p->d_sr == 44100)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						int r ;

						unsigned char *p0, *p1 ;

						

						p0 = s_b+i*w*_c ;

						p1 = s_b+(i+1)*w*_c ;

						if (i+1 >= _sn)

							p1 = p0 ;

						

						/* get the prev sample (one or two) */

						memcpy(d_b+j, p0, w*_c) ;

						j += (w*_c) ;

						

						r = sr_conv(p0, p1, w, _c, buf, 3) ;

						if (r > 0)

						{

							memcpy(d_b+j, buf, r) ;

							j += r ;

						}

						else

						{

							memcpy(d_b+j, p0, w*_c) ;

							j += (w*_c) ;

							memcpy(d_b+j, p0, w*_c) ;

							j += (w*_c) ;

							memcpy(d_b+j, p0, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn/4 ;

				}

			}

			else

			if (p->s_sr == 22050)

			{

				int w = _sw/8 ;

				unsigned char buf[2*4*4] ;

				

				if (p->d_sr == 11025)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						if ((i%2) == 0)

						{

							memcpy(d_b+j, s_b+i*w*_c, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn*2 ;

				}

				else

				if (p->d_sr == 44100)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						int r ;

						unsigned char *p0, *p1 ;

						

						p0 = s_b+i*w*_c ;

						p1 = s_b+(i+1)*w*_c ;

						if (i+1 >= _sn)

							p1 = p0 ;

						

						/* get the prev sample (one or two) */

						memcpy(d_b+j, p0, w*_c) ;

						j += (w*_c) ; 

						

						r = sr_conv(p0, p1, w, _c, buf, 1) ;

						if (r > 0)

						{

							memcpy(d_b+j, buf, r) ;

							j += r ;

						}

						else

						{

							memcpy(d_b+j, p0, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn/2 ;

				}

			}

			else

			if (p->s_sr == 44100)

			{

				int w = _sw/8 ;

				unsigned char buf[2*4*4] ;

				

				if (p->d_sr == 11025)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						if ((i%4) == 0)

						{

							memcpy(d_b+j, s_b+i*w*_c, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn*4 ;

				}

				else

				if (p->d_sr == 22050)

				{

					for (i=0, j=0; i<_sn; i++)

					{

						if ((i%2) == 0)

						{

							memcpy(d_b+j, s_b+i*w*_c, w*_c) ;

							j += (w*_c) ;

						}

					}

					_sr = p->d_sr ;

					_sn = j/(w*_c) ;

					_s_sn = _sn*2 ;

				}

			}

			else

			{

				result = PCMTRAN_ERR_SAMRATE ;

				goto done ;	

			}

			

			/* sample bitWidth convert */

			s_b = (unsigned char *)p->w_b1 ;

			d_b = (unsigned char *)p->w_b0 ;

			if (p->s_sw != p->d_sw)

			{

				int r ;

				int w = _sw/8 ;

				unsigned char buf[2*4*4] ;

				

				for (i=0, j=0; i<_sn; i++)

				{

					r = sw_conv(s_b+i*w*_c, _sw, _c, p->d_sw, buf) ;

					if (r > 0)

					{

						memcpy(d_b+j, buf, r) ;

						j += r ;

					}

					else

					{

						result = PCMTRAN_ERR_SAMWIDTH ;

						goto done ;	

					}

				}

			}

			

			if (output_len)

				*output_len = _sn * p->d_c * (p->d_sw/8) ;

			

			memcpy(*outbuf, d_b, _sn * p->d_c * (p->d_sw/8)) ;

			

			result = PCMTRAN_OK ;

	}

	

done:

	return (result) ;

}



int pcm_transform_getdestsize(unsigned long handle, int source_size, int *dest_size)

{

	int result = -1 ;

	PcmTranCtrl_t *p ; 

	

	p = (PcmTranCtrl_t *)handle ;

	if (p

		&& p->tag == _tag

		&& source_size > 0

		&& dest_size

		)

	{

		int s = source_size / (p->s_c * p->s_sw / 8) ;

		

		if (s > 0)

		{

			int ds = (s * (p->d_c * p->d_sw * p->d_sr)) / (p->s_c * p->s_sw * p->s_sr) ;

			if ((s * (p->d_c * p->d_sw * p->d_sr)) % (p->s_c * p->s_sw * p->s_sr))

				ds ++ ;

			

			if (ds > 0)

			{

				*dest_size = ds * (p->d_c * p->d_sw / 8) ;

				result = 0 ;

			}

		}

	}

	

	return (result) ;

}



/*

	Function:

		Sample rate convert 

	Description:

	Convert bitween 11025Hz,22050Hz,44100Hz PCM Data (8Bit,16Bit,24Bit,32Bit)

*/

static int sr_conv(unsigned char *inbuf0, unsigned char *inbuf1, int width, int channel, unsigned char *outbuf, int level)

{

	int result = 0 ;

	int i, j ;

	

	int w = width ;

	int c = channel ;

	int l = level ;

	

	unsigned char *i0 = inbuf0 ;

	unsigned char *i1 = inbuf1 ;

	unsigned char *o = outbuf ;

	

	long s00, s01 ;

	long s10, s11 ;

	long s0_0, s0_1, s0_2 ;

	long s1_0, s1_1, s1_2 ;

	

	long buf[2*3] ;

	int buf_nums = 0 ;

				

	if (i0

		&& i1

		&& o

		&& width > 0

		&& width <= 4 

		)

	{

		if (w == 1)

		{

			s00 = ((long)i0[0]) ;

			s01 = ((long)i1[0]) ;

			if (c == 2)

			{

				s10 = ((long)i0[w+0]) ;

				s11 = ((long)i1[w+0]) ;

			}

		}

		else

		if (w == 2)

		{

			s00 = (((long)i0[1])<<8) | ((long)i0[0]) ;

			s01 = (((long)i1[1])<<8) | ((long)i1[0]) ;

			if (c == 2)

			{

				s10 = (((long)i0[w+1])<<8) | ((long)i0[w+0]) ;

				s11 = (((long)i1[w+1])<<8) | ((long)i1[w+0]) ;

			}

		}

		else

		if (w == 3)

		{

			s00 = (((long)i0[2])<<16) | (((long)i0[1])<<8) | ((long)i0[0]) ;

			s01 = (((long)i1[2])<<16) | (((long)i1[1])<<8) | ((long)i1[0]) ;

			if (c == 2)

			{

				s10 = (((long)i0[w+2])<<16) | (((long)i0[w+1])<<8) | ((long)i0[w+0]) ;

				s11 = (((long)i1[w+2])<<16) | (((long)i1[w+1])<<8) | ((long)i1[w+0]) ;

			}

		}

		else

		if (w == 4)

		{

			s00 = (((long)i0[3])<<24) | (((long)i0[2])<<16) | (((long)i0[1])<<8) | ((long)i0[0]) ;

			s01 = (((long)i1[3])<<24) | (((long)i1[2])<<16) | (((long)i1[1])<<8) | ((long)i1[0]) ;

			if (c == 2)

			{

				s10 = (((long)i0[w+3])<<24) | (((long)i0[w+2])<<16) | (((long)i0[w+1])<<8) | ((long)i0[w+0]) ;

				s11 = (((long)i1[w+3])<<24) | (((long)i1[w+2])<<16) | (((long)i1[w+1])<<8) | ((long)i1[w+0]) ;

			}

		}

		else

		{

			goto done ;	

		}

		

		if (l == 1)

		{

			s0_0 = s00 + (s01-s00)/2 ;

			buf[0] = s0_0 ;

			buf_nums = 1 ;

			if (c == 2)

			{

				s1_0 = s10 + (s11-s10)/2 ;

				buf[1] = s1_0 ;

				buf_nums += 1 ;

			}

		}

		else

		if (l == 2)

		{

			s0_0 = s00 + (s01-s00)/3 ;

			s0_1 = s00 + (s01-s00)*2/3 ;

			buf[0] = s0_0 ;

			buf[2] = s0_1 ;

			buf_nums = 2 ;

			if (c == 2)

			{

				s1_0 = s10 + (s11-s10)/3 ;

				s1_1 = s10 + (s11-s10)*2/3 ;

				buf[1] = s1_0 ;

				buf[3] = s1_1 ;

				buf_nums += 2 ;

			}

		}

		else

		if (l == 3)

		{

			s0_0 = s00 + (s01-s00)/4 ;

			s0_1 = s00 + (s01-s00)*2/4 ;

			s0_2 = s00 + (s01-s00)*3/4 ;

			buf[0] = s0_0 ;

			buf[2] = s0_1 ;

			buf[4] = s0_2 ;

			buf_nums = 3 ;

			if (c == 2)

			{

				s1_0 = s10 + (s11-s10)/4 ;

				s1_1 = s10 + (s11-s10)*2/4 ;

				s1_2 = s10 + (s11-s10)*3/4 ;

				buf[1] = s1_0 ;

				buf[3] = s1_1 ;

				buf[5] = s1_2 ;

				buf_nums += 3 ;

			}

		}

		else

		{

			goto done ;	

		}

		

		for (i=0; i<buf_nums; i++)

		{

			for (j=0; j<w; j++)

			{

				o[i*w+j] = (unsigned char)((buf[i]>>(j*8))&0xff) ;

				result++ ;

			}

		}

		

	}

	

done:

	return (result) ;

}



/*

	Function:

		Sample width convert 

	Description:

		Convert bitween 8Bit,16Bit,24Bit,32Bit data

*/

static int sw_conv(unsigned char *inbuf, int source_width, int channel, int dest_width, unsigned char *outbuf)

{

	int result = 0 ;

	

	if (inbuf

		&& outbuf

		)

	{

		int n ;

		int sw = source_width/8 ;

		int dw = dest_width/8 ;

		

		if (source_width > dest_width)

		{

			n = (source_width - dest_width)/8 ;

			/* discard lower-bit data */

			memcpy(outbuf, inbuf+n, dw) ;

			result = dw ;

			if (channel == 2)

			{

				/* discard lower-bit data */

				memcpy(outbuf+dw, inbuf+sw+n, dw) ;	

				result += dw ;

			}

		}

		else

		if (source_width < dest_width)

		{

			n = (dest_width - source_width)/8 ;

			/* fill lower-bit data with 0x00 */

			memset(outbuf, 0x00, n) ;

			memcpy(outbuf+n, inbuf, sw) ;

			result = dw ;

			if (channel == 2)

			{

				/* fill lower-bit data with 0x00 */

				memset(outbuf+dw, 0x00, n) ;

				memcpy(outbuf+dw+n, inbuf+sw, sw) ;

				result += dw ;

			}

		}

	}



done:	

	return (result) ;

}

⌨️ 快捷键说明

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