📄 wav.cpp
字号:
// $Revision: 1.1.1.1 $
#include "wavestream.h"
#include "wav.h"
#define mmioFOURCC(ch0, ch1, ch2, ch3) \
((ch0) | \
((ch1) << 8) | \
((ch2) << 16)| \
((ch3) << 24 ))
#define WAVE_FORMAT_PCM 1
typedef struct tagFormatChunk {
word wFormatTag; // 2
word nChannels; // 2
uint nSamplesPerSec; // 4
uint nAvgBytesPerSec; // 4
word nBlockAlign; // 2
word nBitsPerSample; // 2
} FormatChunk;
int cwave::start_read()
{
uint ID;
uint ChunkLen;
FormatChunk FmtChunk;
uint pos;
::fread(&ID,4,1,info->pf); // 'RIFF'
::fread(&RiffLen,4,1,info->pf); // length of RIFF chunk
RiffLen -= ::fread(&ID,4,1,info->pf);
if( ID == mmioFOURCC('W','A','V','E') ) {
::fread(&ID,4,1,info->pf);
::fread(&ChunkLen,4,1,info->pf);
// searching for 'fmt' chunk
while( ID != mmioFOURCC('f','m','t',' ')) {
::fseek(info->pf,ChunkLen,SEEK_CUR);
::fread(&ID,4,1,info->pf);
::fread(&ChunkLen,4,1,info->pf);
}
::fread(&FmtChunk,sizeof(FormatChunk),1,info->pf);
::fseek(info->pf,ChunkLen-sizeof(FormatChunk),SEEK_CUR);
pos = ftell(info->pf);
::fread(&ID,4,1,info->pf);
::fread(&ChunkLen,4,1,info->pf);
// searching for 'DISP' chunk
while(ID != mmioFOURCC('D','I','S','P') ){
::fseek(info->pf,ChunkLen,SEEK_CUR);
::fread(&ID,4,1,info->pf); // Read Chunk ID
::fread(&ChunkLen,4,1,info->pf); // Read Chunk length
if(feof(info->pf)) {
Display = NULL;
break;
}
};
if( ID == mmioFOURCC('D','I','S','P') ) {
::fread(&ID,4,1,info->pf); // 0001
Display = (char*)malloc(ChunkLen);
::fread(Display,1,ChunkLen-4,info->pf);
}
::fseek(info->pf,pos,SEEK_SET);
// searching for 'data' chunk
::fread(&ID,4,1,info->pf);
::fread(&ChunkLen,4,1,info->pf);
while(ID != mmioFOURCC('d','a','t','a') ){
::fseek(info->pf,ChunkLen,SEEK_CUR);
::fread(&ID,4,1,info->pf); // Read Chunk ID
::fread(&ChunkLen,4,1,info->pf); // Read Chunk length
if(feof(info->pf)) return 1;
};
if(FmtChunk.wFormatTag != WAVE_FORMAT_PCM)
return 1; // not in PCM format
info->length = ChunkLen;
info->ch = FmtChunk.nChannels;
info->fs = FmtChunk.nSamplesPerSec;
info->bits = FmtChunk.nBitsPerSample;
info->read_write = 0; // read
info->types = 1; // LSB first
if(info->bits > 8) {
info->length /= 2;
info->offset = 0x0000;
} else {
info->offset = 0x80;
}
pos = ftell(info->pf);
::fseek(info->pf,ChunkLen,SEEK_CUR); // skip data chunk
int smpl_len;
::fread(&ID,4,1,info->pf);
::fread(&smpl_len,4,1,info->pf);
while(ID != mmioFOURCC('s','m','p','l') ){
::fseek(info->pf,smpl_len,SEEK_CUR);
::fread(&ID,4,1,info->pf); // Read Chunk ID
::fread(&smpl_len,4,1,info->pf); // Read Chunk length
if(feof(info->pf)) break;
};
if (ID == mmioFOURCC('s','m','p','l') ){
::fseek(info->pf,44,SEEK_CUR);
smpl_len -= 44;
::fread(&Loop_Start,4,1,info->pf); // Read Loop_Start
::fread(&Loop_End,4,1,info->pf); // Read Loop_End
smpl_len -= 8;
::fseek(info->pf,smpl_len,SEEK_CUR);
printf("Loop at : %d - %d\n",Loop_Start,Loop_End);
} else {
Loop_Start = -1;
Loop_End = -1;
}
::fseek(info->pf,pos,SEEK_SET);
return 0; // normal return
};
return 1;
}
int cwave::start_write(uint format)
{
uint ID;
uint ChunkLen;
FormatChunk FmtChunk;
ID = mmioFOURCC('R','I','F','F');
RiffLen = 0;
::fwrite(&ID,1,4,info->pf);
posriff = ftell(info->pf);
::fwrite(&RiffLen,1,4,info->pf);
ID = mmioFOURCC('W','A','V','E');
RiffLen += ::fwrite(&ID,1,4,info->pf);
ID = mmioFOURCC('f','m','t',' ');
ChunkLen = sizeof(FormatChunk);
RiffLen += ::fwrite(&ID,1,4,info->pf);
RiffLen += ::fwrite(&ChunkLen,1,4,info->pf);
FmtChunk.wFormatTag = WAVE_FORMAT_PCM;
FmtChunk.nChannels = info->ch;
FmtChunk.nSamplesPerSec = info->fs;
FmtChunk.nAvgBytesPerSec = info->fs * info->ch * ((info->bits > 8) ? 2 : 1);
FmtChunk.nBlockAlign = 2;
FmtChunk.nBitsPerSample = info->bits;
RiffLen += ::fwrite(&FmtChunk,1,ChunkLen,info->pf);
ID = mmioFOURCC('d','a','t','a');
RiffLen += ::fwrite(&ID,1,4,info->pf);
posdata = ftell(info->pf);
ChunkLen = 0;
RiffLen += ::fwrite(&ChunkLen,1,4,info->pf);
info->length = 0;
if(info->bits > 8) info->offset = 0;
else info->offset = 0x80;
return 0;
}
void cwave::end_read()
{
}
void cwave::end_write()
{
int pos;
int len,tlen;
uint ID;
int i;
len = info->length*((info->bits > 8) ? 2 : 1);
if(Display != NULL) {
int info_len = strlen(Display);
RiffLen += ::fwrite((void*)"DISP",1,4,info->pf);
int type = info_len + 5; // 0001 & last 0
RiffLen += ::fwrite(&type,1,4,info->pf);
type = 1;
RiffLen += ::fwrite(&type,1,4,info->pf); // 0001
RiffLen += ::fwrite(Display,1,info_len,info->pf);
type = 0;
RiffLen += ::fwrite(&type,1,1,info->pf); // 0
};
::fseek(info->pf,posdata,SEEK_SET);
::fwrite(&len,1,4,info->pf);
::fseek(info->pf,0,SEEK_END);
if(RegNo != 0) {
ID = mmioFOURCC('c','u','e',' ');
::fwrite(&ID,1,4,info->pf); // 'cue '
pos = 0;
posdata = ftell(info->pf);
::fwrite(&pos,1,4,info->pf); // LEN,4
::fwrite(&RegNo,1,4,info->pf); // Total Regions,4
pos += 4;
for(i=0;i<RegNo;i++) {
::fwrite(&(Regions[i]->ID),1,4,info->pf); // ID,4
::fwrite(&(Regions[i]->from),1,4,info->pf); // from,4
ID = mmioFOURCC('d','a','t','a');
::fwrite(&ID,1,4,info->pf); // 'data'
ID = 0;
::fwrite(&ID,1,4,info->pf); //
::fwrite(&ID,1,4,info->pf); //
::fwrite(&(Regions[i]->from),1,4,info->pf); // from,4
pos += 24;
}
::fseek(info->pf,posdata,SEEK_SET);
::fwrite(&pos,1,4,info->pf);
::fseek(info->pf,0,SEEK_END);
len += pos + 8;
ID = mmioFOURCC('L','I','S','T');
::fwrite(&ID,1,4,info->pf); // 'LIST'
pos = 0;
posdata = ftell(info->pf);
::fwrite(&pos,1,4,info->pf); // LEN,4
ID = mmioFOURCC('a','d','t','l');
::fwrite(&ID,1,4,info->pf); // 'adtl'
pos += 4;
for(i=0;i<RegNo;i++) {
if(Regions[i]->len != 0) {
ID = mmioFOURCC('l','t','x','t');
::fwrite(&ID,1,4,info->pf); // 'ltxt'
tlen = 20;
::fwrite(&tlen,1,4,info->pf); // LEN,4
::fwrite(&(Regions[i]->ID),1,4,info->pf); // ID,4
::fwrite(&(Regions[i]->len),1,4,info->pf); // from,4
ID = mmioFOURCC('r','g','n',' ');
::fwrite(&ID,1,4,info->pf); // 'ltxt'
ID = 0;
::fwrite(&ID,1,4,info->pf); //
::fwrite(&ID,1,4,info->pf); //
pos += tlen;
pos += 8; // 'ltxt' + LEN
}
};
for(i=0;i<RegNo;i++) {
ID = mmioFOURCC('l','a','b','l');
::fwrite(&ID,1,4,info->pf); // 'labl'
tlen = strlen(Regions[i]->Label) + 4;
tlen ++;
::fwrite(&tlen,1,4,info->pf); // LEN,4
::fwrite(&(Regions[i]->ID),1,4,info->pf); // ID,4
::fwrite(Regions[i]->Label,1,tlen-4,info->pf);
pos += tlen;
pos += 8;
};
::fseek(info->pf,posdata,SEEK_SET);
::fwrite(&pos,1,4,info->pf);
::fseek(info->pf,0,SEEK_END);
len += pos + 8;
}
::fseek(info->pf,posriff,SEEK_SET);
::fwrite(&len,1,4,info->pf);
::fseek(info->pf,0,SEEK_END);
fclose(info->pf);
info->pf = NULL;
}
void cwave::InitRegion(int Number)
{
RegNo = 0;
Regions = (Region**)malloc(Number*sizeof(Region*));
MaxReg = Number;
for(int i=0;i<Number;i++) Regions[i] = NULL;
}
void cwave::NewRegion(int index,int id,char *label,int from,int len)
{
Regions[index] = (Region*)malloc(sizeof(Region));
Regions[index]->ID = id;
Regions[index]->Label = (char*)malloc(strlen(label));
Regions[index]->from = from;
Regions[index]->len = len;
strcpy(Regions[index]->Label,label);
RegNo++;
}
void cwave::ClearRegion()
{
if(RegNo == 0) return;
for(int i=0;i<MaxReg;i++) {
if(Regions[i] != NULL) {
free(Regions[i]->Label);
free(Regions[i]);
};
}
}
#ifdef _TEST_
#ifdef _OSTREAM_
void help()
{
printf(" useage %wav [options] \n");
printf(" options:\n");
printf(" -o filename : assign output file \n");
printf(" -f fs : assign sample frequency\n");
printf(" -b bits : assign bits per sample (8/16)\n");
printf(" -s : stereo mode\n");
printf(" -h : show this message\n");
exit(0);
}
int main(int argc,char **argv)
{
int fs,ch,bits;
char *fname;
int sample;
argc--;
argv++;
fs = 8000; ch = 1; bits = 16;
fname = "out.wav";
while (argc > 0) {
if( argv[0][0] == '-' ) {
switch(argv[0][1]) {
case 'f' : fs = atoi(argv[1]);
argc--; argv++;
break;
case 's' : ch = 2;
break;
case 'm' : ch = 1;
break;
case 'b' : bits = atoi(argv[1]);
bits = (bits>8) ? 16 : 8;
argc--; argv++;
break;
case 'o' : fname = argv[1];
argc--; argv++;
break;
case 'h' : help();
default :
printf("unkown opiton %s !\n",argv[0]);
help();
}
}
argc--;
argv++;
}
wavestream os(fname,fs);
os.setChannels(ch);
os.setBitsPerSample(bits);
os.start_write(RIFF);
while(scanf("%d",&sample) != EOF) {
os.write((void*)&sample,1);
};
os.end_write();
return 0;
}
#else
int main(int argc,char **argv)
{
short sample;
if(argc<2) return 0;
wavestream is(argv[1]);
is.start_read();
while(is.read(&sample,1)){
printf("%d\n",sample);
}
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -