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

📄 wav.cpp

📁 Enc 压 缩 wav文件为 A16格式的 文件
💻 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 + -