www.pudn.com > 语音语谱图与基频.rar > speechView.cpp


// speechView.cpp : implementation of the CSpeechView class 
// 
 
#include "stdafx.h" 
#include "speech.h" 
#include  
#include "speechDoc.h" 
#include "speechView.h" 
 
//#include "fftw3.h" 
 
#include  
#include "fstream.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
#define FFTSIZE 1024 
#define WINTIME 30 
#define PI 3.14 
#define STEPTIME 10 
#define Samplerate 16000 
///////////////////////////////////////////////////////////////////////////// 
// CSpeechView 
 
IMPLEMENT_DYNCREATE(CSpeechView, CView) 
 
BEGIN_MESSAGE_MAP(CSpeechView, CView) 
	//{{AFX_MSG_MAP(CSpeechView) 
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSpeechView construction/destruction 
 
CSpeechView::CSpeechView() 
{ 
	// TODO: add construction code here 
    m_pWaveBuffer		= NULL; 
    m_flag=0; 
} 
 
CSpeechView::~CSpeechView() 
{ 
	delete m_pWaveBuffer; 
} 
 
BOOL CSpeechView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CSpeechView drawing 
 
void CSpeechView::OnDraw(CDC* pDC) 
{ 
	CSpeechDoc* pDoc = GetDocument(); 
	if(m_flag) 
	{ 
		//m_flag=0; 
		SHORT *psWaveData; 
		unsigned long dwSpeechDataNum; 
		//读出声音信号后,准备画波形图 
	 	psWaveData = (short*) m_pWaveBuffer; 
		//dwSpeechDataNum是声音文件的点数 
		//总的时间可以通过点数除以采样率的时间秒 
		dwSpeechDataNum = m_nWaveLength / sizeof(short); 
		int nMiddle; 
		 
		CPoint pt; 
 
		unsigned long i; 
	 
		CRect rect; 
		GetClientRect(&rect); 
		int t=rect.right-rect.left-30; 
       //坐标轴的绘制  
        int pic1; 
		int pic2; 
		int pic3; 
		pic3=rect.bottom-25; 
		pDC->MoveTo(0,pic3); 
		pDC->LineTo(rect.right,pic3); 
 
		pic2=pic3-rect.bottom/3; 
		pDC->MoveTo(0,pic2); 
		pDC->LineTo(rect.right,pic2); 
 
		pic1=pic2-rect.bottom/3; 
		pDC->MoveTo(0,pic1); 
		pDC->LineTo(rect.right,pic1); 
 
		pDC->MoveTo(30,0); 
		pDC->LineTo(30,rect.bottom); 
         
		nMiddle=pic1/2; 
		//起始点	 
		pt.x=30; 
		pt.y=nMiddle; 
	//	MoveToEx(hMemDC, pt.x, pt.y, NULL); 
		pDC->MoveTo(pt.x,pt.y); 
		short max=0; 
		for(i = 0; i < dwSpeechDataNum; i+=5) 
		  if(psWaveData[i]>max) 
			 max=psWaveData[i]; 
	    double prob=max/32767; 
		 
		for (i = 0; i < dwSpeechDataNum; i+=5) 
		{ 
			//此处的t调整应该根据屏幕坐标来定,时间轴 
			//最大不能超过窗口的宽 
			pt.x = i * t/ dwSpeechDataNum+30; 
			pt.y = nMiddle - psWaveData[i] * nMiddle / max; 
			pDC->LineTo(pt.x, pt.y); 
		} 
 
/* 
        //画语谱图 
        CString filename; 
		double data[FFTSIZE]; 
		int bottom=400; 
		CPoint point; 
		double maxR=0; 
	//	double minR=15; 
		int j; 
 
		for(i=0;idata[j])		    
		          minR=data[j]; 
		  } 
			for(j=0;jMoveTo(point.x,point.y); 
			 int k=255*((maxR-data[j])/(maxR-minR)); 
			if(k>60) 
			{  
				k+=130; 
				if(k>255) 
				k=255; 
		   	} 
			else  
			{ 
				k=k+100; 
		 
			} 
 
			 CPen pen(0,0,RGB(k,k,k)); 
			 CPen *oldpen=pDC->SelectObject(&pen); 
			 pt.y=point.y; 
			 pt.x=point.x+win_size*t/ dwSpeechDataNum; 
			 pDC->LineTo(pt); 
			 pDC->SelectObject(oldpen); 
 
		   } 
		} 
	*/ 
 
	} 
	 
	ASSERT_VALID(pDoc); 
	// TODO: add draw code for native data here 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CSpeechView diagnostics 
 
#ifdef _DEBUG 
void CSpeechView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void CSpeechView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CSpeechDoc* CSpeechView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSpeechDoc))); 
	return (CSpeechDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CSpeechView message handlers 
 
void CSpeechView::OnFileOpen()  
{ 
	// TODO: Add your command handler code here 
    //打开语音文件 
	m_flag=0; 
	//free(m_pWaveBuffer); 
	CFileDialog oFileDlg(TRUE, "wav", "*.wav"); 
	if (oFileDlg.DoModal() != IDOK) return; 
    m_filepath = oFileDlg.GetPathName(); 
    m_name=oFileDlg.GetFileName(); 
	//读取文件 
	ReadFile(m_filepath); 
 
} 
 
 
BOOL CSpeechView::ReadFile(const CString & File) 
{ 
    CString szTemp; 
	FILE* fpWave; 
	char format[9]; 
 
	delete m_pWaveBuffer; 
	 
	fpWave = fopen(File, "rb"); 
	if (fpWave == NULL) 
	{ 
		szTemp.Format("打开文件[%s]失败!", File); 
		::MessageBox(m_hWnd, szTemp, "ERROR", MB_ICONERROR | MB_OK); 
		return false; 
	} 
	 
	fseek(fpWave, 8, SEEK_SET); 
	fread(format, sizeof(char), 8, fpWave); 
	format[8] = 0; 
	fseek(fpWave, 0, SEEK_END); 
	m_nWaveLength = ftell(fpWave); 
	if (m_nWaveLength == 0) 
	{ 
		m_pWaveBuffer = NULL; 
	} 
	else 
	{ 
		fseek(fpWave, 0, SEEK_SET); 
 
		//处理包含文件头的声音文件 
		if ( strcmp(format, "WAVEfmt ")==0 ) 
		{ 
			m_nWaveLength -= 44; 
			fseek(fpWave, 44, SEEK_SET); 
		} 
		m_pWaveBuffer = static_cast(new char[m_nWaveLength]); 
		if (m_pWaveBuffer == NULL) 
		{ 
			szTemp.Format("在读取%s文件之前,分配内存失败", File); 
			::MessageBox(m_hWnd, szTemp, "ERROR", MB_ICONERROR | MB_OK); 
			return false; 
		} 
		else if (m_nWaveLength != fread(m_pWaveBuffer, sizeof(char), m_nWaveLength, fpWave) ) 
		{ 
			szTemp.Format("读取%s文件时出错", File); 
			::MessageBox(m_hWnd, szTemp, "ERROR", MB_ICONERROR | MB_OK); 
			return false; 
		} 
	} 
 
 
    fclose(fpWave); 
//进行基频提取处理 
	 
//	fundamental_frequency((short *)m_pWaveBuffer); 
    m_flag=1; 
	Invalidate(); 
	return true; 
} 
 
void CSpeechView::fundamental_frequency(short *data) 
{ 
   //	int base_frequency; 
 
	int win_size = (int) (Samplerate * WINTIME / 1000); 
	int step_size = (int) (Samplerate * STEPTIME / 1000); 
	int i; 
	int j=m_name.Find('.'); 
	m_name=".\\"+m_name.Left(j); 
	CreateDirectory((LPCTSTR)m_name,NULL); 
	Numzheng=(m_nWaveLength/2-win_size)/step_size; 
	for (i = 0; i >list; 
		data[i]=atof(list); 
	} 
	infile.close(); 
} 
 
int CSpeechView::isgood(double *power) 
{ 
	int i; 
	int max[FFTSIZE];  /* index of local maximum point */ 
	int max_n = 0;     /* number of local maximum point */ 
	int interval[FFTSIZE]; /* distance of two adjacent maximum point */ 
	double average; /* average of the distances */ 
	double  variance; /* variance of the distances */ 
	double sum = 0.0; /* temporary sum */ 
	for (i = 9; i <= 1014; i++) {  
		if ((power[i]>power[i-1]) && 
		    (power[i]>power[i-2]) && 
		    (power[i]>power[i-3]) && 
		    (power[i]>power[i-4]) && 
		    (power[i]>power[i-5]) && 
		    (power[i]>power[i-6]) && 
		    (power[i]>power[i-7]) && 
		    (power[i]>power[i-8]) && 
		    (power[i]>power[i-9]) && 
		    (power[i]>power[i+1]) && 
		    (power[i]>power[i+2]) && 
		    (power[i]>power[i+3]) && 
		    (power[i]>power[i+4]) && 
		    (power[i]>power[i+5]) && 
		    (power[i]>power[i+6]) && 
		    (power[i]>power[i+7]) && 
		    (power[i]>power[i+8]) && 
		    (power[i]>power[i+9])) { 
			max[max_n] = i; 
			max_n++; 
		} 
	} 
 
	for (i=0; i < max_n-1; i++) { 
		interval[i] = max[i+1] - max[i]; 
		sum += interval[i]; 
	} 
	average = sum / (max_n-1); 
	sum = 0; 
	/* standard deviation */ 
	for (i = 0; i < max_n-1; i++) 
		sum += (interval[i]-average)*(interval[i]-average); 
	variance = sum / (max_n-1); 
	 
	if (variance < 25) { 
		printf("max_n = %d variance = %f ", max_n, variance); 
		return 1; 
	} else 
		return 0; 
}