/*
极少接触多媒体编程,这次终于有机会去学习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;
}
}