wavehead.c

来自「一个两碟控制的VCD的代码,两碟之间的转动及连续播放,已大量生产的CODE.」· C语言 代码 · 共 265 行

C
265
字号
/* SCCSID @(#)wavehead.c	1.6 12/10/97 */

 
#include "wavehead.h"
#include "newcomm.h"
#include "../constvar.h"

#define WAVE_FORMAT_PCM			0x0001
#define WAVE_FORMAT_IMAADPCM	0x0011
#define WAVE_FORMAT_MSADPCM		0x0002

extern int WAV_headlen;
extern int wavelen;

typedef struct {
    union { DWORD i; char s[4]; } id;
    DWORD size;
} chunk_header_t;

unsigned int get_LE16(unsigned char *ptr) {
  unsigned int x;
  x = ptr[1];
  x = (x<<8) + ptr[0];
  return x;
}

unsigned int get_LE32(unsigned char *ptr) {
  unsigned int x;
  x = ptr[3];
  x = (x<<8) + ptr[2];
  x = (x<<8) + ptr[1];
  x = (x<<8) + ptr[0];
  return x;
}

static void read_chunk_header(chunk_header_t *chunk_header);
static void read_fact_chunk(chunk_header_t *chunk_header, 
							audio_params_t *audio_params,
							ADPCM_params_t *ADPCM_params);
static void read_data_chunk(chunk_header_t *chunk_header,
							audio_params_t *audio_params);
static DWORD read_id_chunk(void);
static DWORD get_head_info(audio_params_t *audio_params);
static void check_coef(char *dsh, int num_coef, ADPCM_params_t *ADPCM_params);


char *dsh;
static int Type;
static int BufSize;

static char *chunk_type[]={"fact", "DISP", "ACON", "JUNK", "plst", "adtl", 
			  "inst", "smpl", "cue "};

void wave_header(BYTE *sh, int *type, int *bufsize, int *pdata,
				 ADPCM_params_t *ADPCM_params)
{
extern int x10000;
	audio_params_t		audio_params;

	DWORD waveLen = 0;
	DWORD dataaddr;
	int i, j, bsize;
	chunk_header_t	chunk_header;
	align_long_t	al;

	dsh = (char*) sh;
	waveLen=read_id_chunk();
#if 0
	WAV_headlen = 12;
#endif
	read_chunk_header(&chunk_header);
	WAV_headlen = 12 + 8+chunk_header.size;
	al.l = chunk_header.id.i;
	if (strncmp(al.b, "fmt ", 4))
	{
		return ;
	}
	read_fact_chunk(&chunk_header, &audio_params, ADPCM_params);
	while (((int)dsh - (int)sh) < 0x100 )
	{
		read_chunk_header(&chunk_header);
		al.l = chunk_header.id.i;
		
		if (!strncmp(al.b, "data", 4)) {
	                WAV_headlen += 8;
			read_data_chunk(&chunk_header, &audio_params);
			break;   /* once data chunk is reached break */
		} else {
		        for (i=0;i<9;i++)
			   if (!strncmp(al.b, chunk_type[i])) break;
			if (i==9) return;
	                dsh += chunk_header.size;
	                WAV_headlen += 8+chunk_header.size;
		
	        }
#if 0
if((!strncmp(al.b, "fact", 4))
			||	(!strncmp(al.b, "DISP", 4))
			||	(!strncmp(al.b, "ACON", 4))
			||	(!strncmp(al.b, "JUNK", 4))
			||	(!strncmp(al.b, "plst", 4))/* playlist */
			||	(!strncmp(al.b, "adtl", 4))/*associate data chunk*/
			||	(!strncmp(al.b, "inst", 4))
			||	(!strncmp(al.b, "smpl", 4))/*sample chunk*/
			||	(!strncmp(al.b, "cue ", 4)))/*cue point chunk*/
		{
	            dsh += chunk_header.size;
	            WAV_headlen += 8+chunk_header.size;
		} else {
			return;
		}
#endif
	}
	dataaddr = get_head_info(&audio_params);
	Type += x10000;	/* WAV */
	*type = (int)Type;
	*bufsize = (int)BufSize;
	*pdata = (int)dataaddr;
	WAV_headlen = ((WAV_headlen + 63)>>6)<<6;
}

static void read_chunk_header(chunk_header_t *chunk_header) {
    int i;
    for (i=0;i<4;i++) chunk_header->id.s[i] = dsh[i];
    dsh+=4;
    chunk_header->size = get_LE32(dsh);
    dsh+=4;
}

static void read_data_chunk(chunk_header_t *chunk_header, audio_params_t *audio_params)
{
    audio_params->data_params.data_p = (int)dsh;
    audio_params->data_params.data_len = chunk_header->size;
    wavelen = chunk_header->size;
    dsh += wavelen;
}

static void read_fact_chunk(chunk_header_t *chunk_header, 
	audio_params_t *audio_params, ADPCM_params_t *ADPCM_params)
{
	int i, j;
	unsigned int formatTag, num_coef;
	
	formatTag = get_LE16(dsh);  dsh += 2;
	audio_params->n_channels = get_LE16(dsh);   dsh += 2;
	audio_params->samp_rate = get_LE32(dsh);    dsh += 4;
	dsh+=4; /* two channel sample rate */
	switch(formatTag) {
	case WAVE_FORMAT_PCM:
		Type = 0; 
                dsh+=2;
		audio_params->samp_width = get_LE16(dsh);
		dsh+=2;
		dsh+=chunk_header->size-0x10;
		break;
#ifdef SOUND_ADPCM
	case WAVE_FORMAT_IMAADPCM:
		Type = 0x10;
		ADPCM_params->n_block_alignment = get_LE16(dsh);
		ADPCM_params->n_bits_per_sample = get_LE16(dsh+2);
		audio_params->samp_width = get_LE16(dsh+2);
		dsh+=4;
		ADPCM_params->n_samples_per_block = get_LE16(dsh+2);
		dsh += chunk_header->size;
		break;
	case WAVE_FORMAT_MSADPCM:
		Type = 0x20;
		ADPCM_params->n_block_alignment = get_LE16(dsh);
		ADPCM_params->n_bits_per_sample = get_LE16(dsh+2);
		audio_params->samp_width = get_LE16(dsh+2);
		dsh+=4;
		ADPCM_params->n_samples_per_block = get_LE16(dsh+2);
		dsh+=4;
		num_coef = get_LE16(dsh);
		check_coef(dsh, num_coef, ADPCM_params);
		dsh += chunk_header->size;
		break;
#endif
	}
}

#ifdef SOUND_ADPCM
static short gaiCoef1[] = { 256,  512,  0, 192, 240,  460,  392 };
static short gaiCoef2[] = {   0, -256,  0,  64,   0, -208, -232 };


static void check_coef(char *dsh, int num_coef, ADPCM_params_t *ADPCM_params)
{
	short coef1[7], coef2[7];
	int i;

	for(i=0; i<7; i++)
	{
		coef1[0] = get_LE16(dsh+2);  /* high_WORD(*dsh); */
		dsh+=4;
		coef2[0] = get_LE16(dsh); /* low_WORD(*dsh); */
	}
	if (num_coef>7)
		num_coef -= 7;
	for (i=0; i<num_coef; i++)
	{
		ADPCM_params->coef1[i] = get_LE16(dsh+2); /*high_WORD(*dsh);*/
		dsh+=4;
		ADPCM_params->coef2[i] = get_LE16(dsh); /*low_WORD(*dsh);*/
	}
}

#endif /* SOUND_ADPCM */
static DWORD get_head_info(audio_params_t *audio_params)
{	
	int shif = 0;

	if (audio_params->n_channels == 1)
	{
		Type |= 0x02;
		shif += 1;
	}
	if (audio_params->samp_width == 8)
	{
		Type |= 0x01;
		shif += 1;
	}
	
	if (audio_params->samp_rate == 0xac44);
	else if (audio_params->samp_rate == 0x5622)
	{
		Type |= 0x04;
		shif += 1;
	}
	else if (	(audio_params->samp_rate == 0x2b11) ||
				(audio_params->samp_rate == 0x2b77))
	{
		Type |= 0x08;
		shif += 2;
	}
	
	BufSize = 256>>shif;
	return(audio_params->data_params.data_p);
}

static DWORD read_id_chunk()
{
	DWORD waveLen;
	DWORD idRIFF;
	DWORD idWAVE;
	align_long_t al,bl;
	
/*
	idRIFF = get_int32(dsh);
	al.l = idRIFF;
*/
	dsh+=4;
        
	waveLen = get_LE32(dsh);
	dsh+=4;
/*
	idWAVE = get_int32(dsh);
	al.l = idWAVE;
*/
	dsh+=4;

	return waveLen;
}

⌨️ 快捷键说明

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