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;i data[j]) minR=data[j]; } for(j=0;j MoveTo(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; }