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 + -
显示快捷键?