WAVE文件分析与编程(VC++6.0)

/*

极少接触多媒体编程,这次终于有机会去学习WAVE文件格式啦,原来WAVE文件格式如此简单,^_^

Thanks to http://ccrma.stanford.edu/courses/422/projects/WaveFormat/,

http://blog.vckbase.com/star/archive/2005/05/24/5745.html(宁静致远的Blog)

*/

//
// Author: Wen Xiaoyong(Wenxy), 20070802,a.m., wen_kernel@163.com
// Fix history:
//
// wenxy add begin -----------------------------
#define TIME_WAVE_SEGEMENT 3 // 3 seconds
#define MAX_SILENCE_16BIT 1000 // 16 bit sampling frequency, silence value
#define MAX_SILENCE_8BIT 128 // 8 bit sampling frequency, silence value
#define MAX_COUNT_YAWP 200  // max yawp count

unsigned int g_uYawpCount = 0; // yawp count
bool g_bFindSilence = false; // silence flag
long int g_lSegmentBit = 0;  // bits of the wave segment
double g_dCurrentTime = 0;  // current time
double g_dBeginTime = 0;  // silence area begin time
double g_dEndTime = 0;   // silence area end time
double g_dTotalTime = 0;  // wave file totle time
// wenxy add end -----------------------------

 

short mono1_stereo2 = 1;
long samplingfreq = 11025;
short bitlength = 8; // 8
long totalbytes = 11025;
long bytesinfile = 11025;
short chbytes_per_sample = 1;
short bytes_per_sample = 1;
long bytes_per_sec = 11025;
long wavesize = 11025;
int dotn = 500; // 500
double* InWave;
double* InWaveR;
BOOL allocated = FALSE;
BOOL loaded = FALSE;
int xstep = 1; // 1
int yframe = 100; // 100
int yrng = 300; // 10000

unsigned long get_ulong(FILE *f)
{
    unsigned char s[4];
 unsigned res;

    if (fread(s, 4, 1, f) != 1) {
  res = 0;
    } else {
  res = s[0] + 256LU * (s[1] + 256LU * (s[2] + 256LU * s[3]));
 }
    return res;
}

unsigned get_ushort(FILE *f)
{
    unsigned char s[2];
 unsigned res;

    if (fread(s, 2, 1, f) != 1) {
  res = 0;
    } else {
  res = s[0] + 256U * s[1];
 }
    return res;
}

unsigned get_ubyte(FILE *f)
{
    unsigned char s[1];
 unsigned res;

    if (fread(s, 1, 1, f) != 1) {
  res = 0;
    } else {
  res = s[0];
 }
    return res;
}

void AllocateMemory()
{
 if( allocated ) {
  free(InWave);
  free(InWaveR);
 }
 InWave = (double *)calloc(wavesize, sizeof(double));
 InWaveR = (double *)calloc(wavesize, sizeof(double));
 allocated = TRUE;
}

void AllocateMemory(unsigned int uSize)
{
 if( allocated ) {
  free(InWave);
  free(InWaveR);
 }
 InWave = (double *)calloc(uSize, sizeof(double));
 InWaveR = (double *)calloc(uSize, sizeof(double));
 allocated = TRUE;
}

void FreeMemory()
{
 if(allocated)
 {
  free(InWave);
  free(InWaveR);
  allocated = TRUE;
 }
}

void GetWavInfo()
{
 unsigned long len;
 unsigned char s[10];
 int i;
 long fmtbytes;
 FILE *ifp;
 CString filenameld;
 CFileDialog dlgF(TRUE, "NULL", "*.wav");
 
 if( dlgF.DoModal() == IDOK) 
 {
  filenameld = dlgF.GetPathName();
  ifp = fopen( filenameld, "rb" );
  if (ifp != NULL)
  {
   fread(s, 4, 1, ifp);   // "RIFF"
   bytesinfile = get_ulong(ifp); // 4 bytes, total bytes in the file
   fread(s, 8, 1, ifp);   // "WAVEfmt"
   fmtbytes = get_ulong(ifp);  // 4 bytes, header size
   len = get_ushort(ifp);   // 2 bytes, 1: pcm
   mono1_stereo2 = get_ushort(ifp); // 1: mono, 2; stereo
   samplingfreq = get_ulong(ifp); // sampling frequency
   bytes_per_sec = get_ulong(ifp); // bytes per second
   chbytes_per_sample = get_ushort(ifp); // bytes per sample
   bitlength = get_ushort(ifp); // bit length
   for (i = 0; i < (fmtbytes-16)/2; i++ )
   {
    len = get_ushort(ifp); // skip redundant header information
   }
   do{ // look for "data" chunk
    fread(s, 4, 1, ifp); // expect "data"
    if(((s[0] == 'd')&(s[1] == 'a')&(s[2] == 't')&(s[3] == 'a')) == 0)
    { // step over chunks unless it's "data" chunk
     len = get_ulong(ifp);
     fseek(ifp, len, SEEK_CUR);
    }
    else
    {
     break ;
    }
   }while(1);
   totalbytes = get_ulong(ifp); // total bytes of wav data
   bytes_per_sample = bitlength / 8;
   wavesize = totalbytes / (mono1_stereo2 * bytes_per_sample);
   g_dTotalTime = wavesize / (double)samplingfreq;
   int i, m;
   short x;

   //AllocateMemory();
   g_lSegmentBit = TIME_WAVE_SEGEMENT * mono1_stereo2 * bytes_per_sample /
        * samplingfreq;
   AllocateMemory(g_lSegmentBit);
   
   // analyse silence begin -----------------------------------
   CString strMax;
   short int nMax = 0;
   g_uYawpCount = 0;
   g_bFindSilence = false;
   if (mono1_stereo2 == 1)
   {
    for (i = 0; i < g_lSegmentBit; i++)
    { // read mono wav data
     if (fread(s, bytes_per_sample, 1, ifp) != 1)
     {
      break;
     }
     //if (bytes_per_sample == 2) x = (short)(s[0] + 256 * s[1]);
     
     if (bytes_per_sample == 2)
     {
      x = (short int)(s[0] + 256 * s[1]);
     }
     else      
     {
      x = (short)(s[0]) - 128;
     }
     InWave[i] = (double)(x);
     if(abs(x) >= MAX_SILENCE_16BIT)
     {
      g_uYawpCount ++;
     }
     // not silence segment
     if(g_uYawpCount > MAX_COUNT_YAWP)
     {
      break;
     }
    }
    // find a silence segment
    if(g_uYawpCount <= MAX_COUNT_YAWP)
    {
     g_bFindSilence = true;
    }
    strMax.Format("Yawp=[%d], silence=%d", g_uYawpCount, g_bFindSilence);
    SetWindowText(theApp.GetMainWnd()->m_hWnd, strMax);

   }
   else
   {
    for (i = 0; i < wavesize * 2; i++)
    { // read stereo wav data
     m = i / 2;
     if (fread(s, bytes_per_sample, 1, ifp) != 1) break;
     if (bytes_per_sample == 2) x = (short)(s[0] + 256 * s[1]);
     else x = (short)(s[0]) - 128;
     if(i%2==0) InWave[m] = (double)(x);
     else InWaveR[m] = (double)(x);
    }
   }
   
   /*
   CString strMax;
   short int nMax = 0;
   if (mono1_stereo2 == 1)
   {
    for (i = 0; i < wavesize; i++)
    { // read mono wav data
     if (fread(s, bytes_per_sample, 1, ifp) != 1) break;
     //if (bytes_per_sample == 2) x = (short)(s[0] + 256 * s[1]);
     if (bytes_per_sample == 2) x = (short int)(s[0] + 256 * s[1]);
     else x = (short)(s[0]) - 128;
     InWave[i] = (double)(x);
     if(abs(nMax) < abs(x))
     {
      nMax = x;
     }
     
    }
    strMax.Format("%d", nMax);
    SetWindowText(theApp.GetMainWnd()->m_hWnd, strMax);

   } else
   {
    for (i = 0; i < wavesize * 2; i++)
    { // read stereo wav data
     m = i / 2;
     if (fread(s, bytes_per_sample, 1, ifp) != 1) break;
     if (bytes_per_sample == 2) x = (short)(s[0] + 256 * s[1]);
     else x = (short)(s[0]) - 128;
     if(i%2==0) InWave[m] = (double)(x);
     else InWaveR[m] = (double)(x);
    }
   }
   */
   // analyse silence end -----------------------------------

   fclose( ifp );
   loaded = TRUE;
  }
 }
}

void InfoDraw(CDC* pDC, int x1, int y1)
{
 char tmpchar[12];

 if( mono1_stereo2 == 1 ) pDC->TextOut( x1 + 10, y1 + 10, "Mono");
 else pDC->TextOut( x1 + 10, y1 + 10, "Stereo");

 pDC->TextOut( x1 + 80, y1 + 10, "Sampling Freq");
 sprintf(tmpchar,"%6d", samplingfreq);
 pDC->TextOut( x1 + 80, y1 + 30, tmpchar);

 pDC->TextOut( x1 + 200, y1 + 10, "Bit Length");
 sprintf(tmpchar,"%3d", bitlength);
 pDC->TextOut( x1 + 200, y1 + 30, tmpchar);

 pDC->TextOut( x1 + 300, y1 + 10, "Total Bytes");
 sprintf(tmpchar,"%8d", totalbytes);
 pDC->TextOut( x1 + 300, y1 + 30, tmpchar);

 pDC->TextOut( x1 + 400, y1 + 10, "Time Length");
 sprintf(tmpchar,"%7.4f", (double)wavesize/(double)samplingfreq);
 pDC->TextOut( x1 + 400, y1 + 30, tmpchar);
}

 

void WaveDraw(CDC* pDC, int x1, int y1, double* InW)
{
 CPen myPen;
 CPen* pOldPen;

 int i;
 int ytmp;
 char tmpchar[12];

 sprintf(tmpchar,"%7d", yrng);
 pDC->TextOut( x1 - 55, y1 - yframe - 8, tmpchar);
 sprintf(tmpchar,"%6d", -yrng);
 pDC->TextOut( x1 - 55, y1 + yframe - 8, tmpchar);
 pDC->TextOut( x1 - 20, y1 - 8, "0");

 sprintf(tmpchar,"%7.4f", (double)(dotn/2)/(double)samplingfreq);
 pDC->TextOut( x1 + xstep * dotn/2 - 30, y1 + yframe + 8, tmpchar);
 sprintf(tmpchar,"%7.4f", (double)dotn/(double)samplingfreq);
 pDC->TextOut( x1 + xstep * dotn - 30, y1 + yframe + 8, tmpchar);

 myPen.CreatePen(PS_DOT, 1, RGB(0,255,0));
 pOldPen = pDC->SelectObject(&myPen);

 pDC->MoveTo(x1, y1);
 pDC->LineTo(x1 + dotn * xstep, y1);

 pDC->MoveTo(x1, y1 - yframe);
 pDC->LineTo(x1 + dotn * xstep, y1 - yframe);

 pDC->MoveTo(x1, y1 + yframe);
 pDC->LineTo(x1 + dotn * xstep, y1 + yframe);

 pDC->MoveTo(x1, y1 - yframe);
 pDC->LineTo(x1, y1 + yframe);
 pDC->MoveTo(x1 + (int)(dotn * xstep / 2), y1 - yframe);
 pDC->LineTo(x1 + (int)(dotn * xstep / 2), y1 + yframe);
 pDC->MoveTo(x1 + dotn * xstep, y1 - yframe);
 pDC->LineTo(x1 + dotn * xstep, y1 + yframe);

 pDC->SelectObject(pOldPen);
 myPen.DeleteObject();

 myPen.CreatePen(PS_SOLID, 1, RGB(0,0,255));
 pOldPen = pDC->SelectObject(&myPen);

 int nEnd = wavesize;
 //wavesize = totalbytes / (mono1_stereo2 * bytes_per_sample);

 //for(i = 0; i < dotn-2; i++)
 for(i = 0; i < nEnd-2; i++)
 {
  ytmp = (int)(-yframe * InW[i+0] / yrng);
  if( ytmp > yframe ) ytmp = yframe;
  if( ytmp < -yframe ) ytmp = -yframe;
  pDC->MoveTo(x1 + (i+0) * xstep, y1 + ytmp);
  ytmp = (int)(-yframe * InW[i+1] / yrng);
  if( ytmp > yframe ) ytmp = yframe;
  if( ytmp < -yframe ) ytmp = -yframe;
  pDC->LineTo(x1 + (i+1) * xstep, y1 + ytmp);
 }
 pDC->SelectObject(pOldPen);
 myPen.DeleteObject();
}

//


void CAnalyseSilenceTimeDlg::OnButtonLoadFile()
{
 // TODO: Add your control notification handler code here
 //ShowFileDailog(m_strFile);
 GetWavInfo();
// CDC *pWindowDC = GetWindowDC();
// if(pWindowDC == NULL)
// {
//  return;
//  }
// InfoDraw( pWindowDC, 100, 50);
// double dInW = 0;
// WaveDraw(pWindowDC, 100, 250, InWave);
// //AfxMessageBox(m_strFile);
// if(pWindowDC)
// {
//  ReleaseDC(pWindowDC);
//  pWindowDC = NULL;
// }
 m_bLoadWaveFile = true;
}

void CAnalyseSilenceTimeDlg::OnClose()
{
 // TODO: Add your message handler code here and/or call default
 FreeMemory(); 
 CDialog::OnClose();
}

void CAnalyseSilenceTimeDlg::OnSize(UINT nType, int cx, int cy)
{
 CDialog::OnSize(nType, cx, cy);
 
 // TODO: Add your message handler code here
 //DrawWaveInfor(); 
}

void CAnalyseSilenceTimeDlg::OnMove(int x, int y)
{
 CDialog::OnMove(x, y);
 
 // TODO: Add your message handler code here
 //DrawWaveInfor();
}

void CAnalyseSilenceTimeDlg::DrawWaveInfor()
{
 if(m_bLoadWaveFile == false)
 {
  return;
 }
 CDC *pWindowDC = GetWindowDC();
 if(pWindowDC == NULL)
 {
  return;
 }
 InfoDraw( pWindowDC, 100, 50);
 double dInW = 0;
 WaveDraw(pWindowDC, 100, 250, InWave);
 //AfxMessageBox(m_strFile);
 if(pWindowDC)
 {
  ReleaseDC(pWindowDC);
  pWindowDC = NULL;
 }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值