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

📄 bwcnv.c

📁 BlueWave PCM8 adpcm 编码解码工具
💻 C
字号:
/*--------------------------------------------------------
	MS PCM to BrueWave format Converter
	Copyright(C)2001 BluePlanet

	2001/1/27 ver.0.1
--------------------------------------------------------*/

#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>

/*----------------------------------
	DEFINEs
-----------------------------------*/
#define	VERSION		"0.1"
#define	BUFF_SIZE	0x1000
#define	FNAME_SIZE	256
#define	DST_EXT		".fr"
#define	BASE_FREQ	12000
#define	WAV_HEADER_SIZE		sizeof(WAV_HEADER)
#define	BW_HEADER_SIZE		sizeof(BW_HEADER)


/*----------------------------------
	PCM MODEs
-----------------------------------*/
#define	PCM_ID_WAV		1
#define	PCM_ID_X68		2

/*----------------------------------
	TYPEDEFs
-----------------------------------*/
typedef unsigned char	uchar;
typedef unsigned short	ushort;
typedef unsigned long	ulong;

typedef struct{
	char	riff[4];
	ulong	file_size;
	char	wavefmt[8];
	ulong	head_size;
	ushort	data_type;
	ushort	channels1;
	ulong	rate;
	ulong	rate_avg;
	ushort	channels2;
	ushort	smpl_bits;
	ulong	data;
	ulong	pcm_size;
} WAV_HEADER;

typedef struct{
	char	magic[2];
	char	type[2];
	ushort	file_size;
	ushort	id;
	ulong	pcm_size;
	char	pcm_type;
	char	rate;
	char	reserve[2];
} BW_HEADER;

typedef struct{
	int			err_no;
	char		src_fname[FNAME_SIZE];
	char		dst_fname[FNAME_SIZE];
	ulong		pcm_size;
	BW_HEADER	h;
} PARAM;

/*----------------------------------
	VARIABLEs
-----------------------------------*/
static BW_HEADER default_bw_header = {
		{ 'F', 'R' },	/* magic	 */
		{ 'B', 'W' },	/* type		 */
		0,				/* file size */
		0,				/* id		 */
		0,				/* pcm size	 */
		PCM_ID_WAV,		/* pcm type	 */
		1,				/* rate, freq = 16000Hz / rate */
		0				/* reserve	 */
	};
static int	s_level = 0;
static int	a_level = 0;

/*----------------------------------
	TABLEs
-----------------------------------*/
static unsigned scaleval[]={
		 16,	 17,	  19,	  21,	  23,	  25,	  28,
		 31,	 34,	  37,	  41,	  45,	  50,	  55,
		 60,	 66,	  73,	  80,	  88,	  97,	 107,
		118,	130,	 143,	 157,	 173,	 190,	 209,
		230,	253,	 279,	 307,	 337,	 371,	 408,
		449,	494,	 544,	 598,	 658,	 724,	 796,
		876,	963,	1060,	1166,	1282,	1411,	1552
	};
static unsigned levelchg[]={-1,-1,-1,-1,2,4,6,8};

/*----------------------------------
	CODEs
-----------------------------------*/
int	adpcm2pcm(int d)
{
	int		a, q;

	a = (((d & 7)<<1) + 1) * scaleval[s_level];
	a >>= 3;
	if(d&8) a = -a;
	a_level += a;
	if( a_level>511	 ) a_level=	 511;
	if( a_level<-512 ) a_level= -512;
	q = a_level<<6;
	s_level += levelchg[d&7];
	if( s_level<0  ) s_level = 0;
	if( s_level>48 ) s_level = 48;

	return q;
}

int	pcm2adpcm(int d)
{
	int		a, q;

	d -= 0x8000;
	a = (d>>6) - a_level;
	q = 0;
	if( a<0 ){
		a = -a;
		q = 8;
	}
	a /= (scaleval[s_level]>>3);
	if( a>=16 ){
		q |= 7;
	}
	else if( a!=0 ){
		q |= ((a-1)>>1);
	}
	adpcm2pcm( q );

	return q;
}

void wav2bw( FILE *dst_fp, FILE *src_fp, PARAM *param )
{
	int		i, n, m, d;
	int		end_flg;
	ulong	size, read_size;
	char	*p, *q;
	static char	src_buff[BUFF_SIZE];
	static char	dst_buff[BUFF_SIZE];

	end_flg = 0;
	size = param->pcm_size;
	if( param->h.pcm_type==PCM_ID_WAV ){
		while( end_flg==0 ){
			read_size = (size>BUFF_SIZE) ? BUFF_SIZE : size;
			size -= read_size;
			n = fread( src_buff, 1, read_size, src_fp );
			if( n<BUFF_SIZE ){
				end_flg = 1;
				m = 0x0010 - (n&0x000f);
				if( m!=0x0010 ){
					memset( src_buff+n, 0x80, m );
					n += m;
				}
				if( n==0 ){
					break;
				}
			}
			fwrite( src_buff, 1, n, dst_fp );
			param->h.pcm_size += n;
		}
	}
	else{
		while( end_flg==0 ){
			read_size = (size>BUFF_SIZE) ? BUFF_SIZE : size;
			size -= read_size;
			n = fread( src_buff, 1, read_size, src_fp );
			if( n<BUFF_SIZE ){
				end_flg = 1;
				m = 0x0020 - (n&0x001f);
				if( m!=0x0020 ){
					memset( src_buff+n, 0x80, m );
					n += m;
				}
			}
			p = src_buff;
			q = dst_buff;
			m = n/2;
			for( i=0; i<m; i++ ){
				d  =  pcm2adpcm( (*p++)<<8 );
				d |= (pcm2adpcm( (*p++)<<8 ))<<4;
				*q++ = d;
			}
			fwrite( dst_buff, 1, m, dst_fp );
			param->h.pcm_size += m;
		}
	}

	return;
}

int init_param(int argc, char **argv, PARAM *p)
{
	int i;
	char	*q;
	int	err_flg;

	strncpy(p->src_fname, "", FNAME_SIZE);
	strncpy(p->dst_fname, "", FNAME_SIZE);
	p->err_no = 0;
	p->h = default_bw_header;
	s_level = 0;
	a_level = 0;
	err_flg	  = 0;
	argv++;

	for( i=1; i<argc; i++, argv++ ){
		if( **argv=='-' || **argv=='/' ){
			switch( *(*argv+1) ){
			case	'F':
			case	'f':	p->h.pcm_type = atoi(*argv+2);
							break;
			case	'd':
			case	'D':	p->h.id = atoi(*argv+2);
							break;
			default:
				err_flg = 1;
				break;
			}
		}
		else{
			if( strlen(p->src_fname)==0 ){
				strncpy(p->src_fname, *argv, FNAME_SIZE-8);
			}
			else if( strlen(p->dst_fname)==0 ){
				strncpy(p->dst_fname, *argv, FNAME_SIZE-8);
			}
			else{
				err_flg = 1;
			}
		}
	}
	if( strlen(p->src_fname)==0 ){
		err_flg = 2;
	}
	else if( strlen(p->dst_fname)==0 ){
		strcpy(p->dst_fname, p->src_fname);
		q = strrchr(p->dst_fname, '.');
		if( q>strrchr(p->dst_fname, '\\') ){
			*q = '\0';
		}
		strcat(p->dst_fname, DST_EXT);
	}

	return err_flg;
}

FILE *fopen_src(PARAM *p)
{
	FILE	*fp;
	WAV_HEADER	wav_info;

	fp = fopen(p->src_fname, "rb");
	if( fp!=NULL ){
		fread( &wav_info, WAV_HEADER_SIZE, 1, fp );
		if( strncmp( wav_info.riff, "RIFF", 4)!=0
		 || wav_info.channels1!=1
		 || wav_info.smpl_bits>16
		){
			fclose( fp );
			fp=NULL;
			p->err_no = 2;
		}
		p->h.rate = (int)((BASE_FREQ + wav_info.rate/2) / wav_info.rate);
		p->pcm_size = wav_info.pcm_size;
	}
	else{
		p->err_no = 1;
	}

	return fp;
}
FILE *fopen_dst(PARAM *p)
{
	FILE	*fp;

	fp = fopen(p->dst_fname, "wb");
	if( fp!=NULL ){
		fwrite( &(p->h), BW_HEADER_SIZE, 1, fp );
	}
	else{
		p->err_no = 1;
	}

	return fp;
}

void write_header( FILE *fp, PARAM *p )
{
	p->h.file_size = (p->h.pcm_size + 16L)>>4;


	rewind( fp );
	fwrite( &(p->h), BW_HEADER_SIZE, 1, fp );
}

void put_version(void)
{
	fprintf( stderr, "MS-PCM to BrueWave Converter BWCNV ver.%s  (C)2001 BluePlanet\n", VERSION );
}
void usage(void)
{
	fprintf( stderr, "Usage: bwcnv [<optines>] <source filename> [<destination filename>]\n", VERSION );
	fprintf( stderr, "-f<format>: <format> is 1=8bit PCM(default), 2=4bit ADPCM\n" );
	fprintf( stderr, "-d<id>    : <id> is Resource ID. (default=0)\n" );
}
int main(int argc, char **argv)
{
	int ret;
	PARAM	param;
	FILE	*src_fp, *dst_fp;

	put_version();
	ret = init_param( argc, argv, &param );
	if( ret ){
		usage();
		return	ret;
	}

	src_fp = fopen_src( &param );
	if( src_fp==NULL ){
		if( param.err_no==1 ){
			fprintf( stderr, "\"%s\" open error.\n", param.src_fname );
		}
		else{
			fprintf( stderr, "\"%s\" format error. Monaural 8bit only.\n", param.src_fname );
		}
		return	ret;
	}
	dst_fp = fopen_dst( &param );
	if( dst_fp==NULL ){
		fprintf( stderr, "\"%s\" open error.\n", param.dst_fname );
		fclose( src_fp );
		return	ret;
	}

	wav2bw( dst_fp, src_fp, &param );
	write_header( dst_fp, &param );

	fclose( src_fp );
	fclose( dst_fp );

	return 0;
}

⌨️ 快捷键说明

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