CWaveFile.CPP
上传用户:btjhwmj
上传日期:2007-03-02
资源大小:7k
文件大小:12k
源码类别:

Audio

开发平台:

WINDOWS

  1. //CWaveViewCtrl.CPP
  2. #include "stdafx.h"
  3. #include "CWaveFile.h"
  4. static const IID IID_DirectSound= {0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60};
  5. UINT TimerID;
  6. IMPLEMENT_SERIAL(CWaveViewCtrl,CObject,VERSIONABLE_SCHEMA|2)
  7. UINT DrawThread(LPVOID pParam);
  8. //Message Map
  9. BEGIN_MESSAGE_MAP( CWaveViewCtrl, CWnd)
  10. //{{AFX_MSG_MAP(CWaveEditorView)
  11. ON_WM_LBUTTONDOWN()
  12. ON_WM_LBUTTONUP()
  13. ON_WM_MOUSEMOVE()
  14. ON_WM_KILLFOCUS()
  15. ON_WM_SETFOCUS()
  16. ON_WM_CREATE()
  17. ON_WM_TIMER()
  18. ON_WM_PAINT()
  19. ON_WM_SIZE()
  20. //}}AFX_MSG_MAP
  21. END_MESSAGE_MAP()
  22. //<<<<<<<Constructors>>>>>>>>>
  23. CWaveViewCtrl::CWaveViewCtrl()
  24. {
  25. m_selpoint=-1;
  26. m_shiftcaret=false;
  27. DSound=NULL;
  28. DSoundBuff=NULL;
  29. isComm=false;
  30. m_MouseSel=false;
  31. m_PBP.x=m_PBP.y=NULL;
  32. }
  33. //******************************
  34. //<<<<<<<<<<<Overrides>>>>>>>>>>>>
  35. BOOL CWaveViewCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
  36. {
  37. pContext = NULL;
  38. static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
  39. return CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE,
  40. className, NULL, dwStyle, 
  41. rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  42. pParentWnd->GetSafeHwnd(), (HMENU) nID);
  43. }
  44. int CWaveViewCtrl::OnCreate( LPCREATESTRUCT lpCreateStruct )
  45. {
  46. if (CWnd::OnCreate(lpCreateStruct) == -1)
  47. return -1;
  48. m_selpoint=-1;
  49. // hWnd=GetSafeHwnd();
  50. GetClientRect(&rect);
  51. // CreateCaret(true);
  52. return 0;
  53. }
  54. void CWaveViewCtrl::Serialize( CArchive& ar )
  55. {
  56. CObject::Serialize(ar);
  57. if(ar.IsLoading ())
  58. {
  59. CFile *file;
  60. char* groupID;
  61. file=ar.GetFile();
  62. HANDLE m_hMap=::CreateFileMapping((HANDLE)file->m_hFile,NULL,PAGE_READONLY,0,0,NULL);
  63. LPVOID lpvFile=::MapViewOfFile(m_hMap,FILE_MAP_READ,0,0,0);
  64. int p=0;
  65. m_pRiff=(RIFF*)lpvFile;
  66. p+=sizeof(*m_pRiff);
  67. if(memcmp(m_pRiff->ID ,"RIFF",sizeof(m_pRiff->ID))==0)  //for reading file heder difinetion
  68. {
  69. groupID=(char*)lpvFile+p;p+=4;
  70. if(memcmp(groupID ,"WAVE",sizeof(groupID))!=0)
  71. {
  72. AfxThrowArchiveException(CArchiveException::badIndex);
  73. }
  74. }
  75. else 
  76. AfxThrowArchiveException(CArchiveException::badIndex);
  77. m_pRiff=(RIFF*)((BYTE*)lpvFile+p);
  78. p+=sizeof(*m_pRiff);
  79. while(memcmp(m_pRiff->ID ,"fmt ",sizeof(m_pRiff->ID)))  //for reading format chunk 
  80. {
  81. p+=m_pRiff->Size;
  82. m_pRiff=(RIFF*)((BYTE*)lpvFile+p);
  83. p+=sizeof(*m_pRiff);
  84. }
  85. m_pfch=(fchunk*)((BYTE*)lpvFile+p);
  86. if(m_pfch->wFormatTag ==1)
  87. {
  88. do{
  89. p+=m_pRiff->Size;
  90. m_pRiff=(RIFF*)((BYTE*)lpvFile+p);
  91. p+=sizeof(*m_pRiff);
  92. }while(memcmp(m_pRiff->ID ,"data",sizeof(m_pRiff->ID)));
  93. m_data=(BYTE*)lpvFile+p;
  94. isComm=true;
  95. m_MouseSel=true;
  96. }
  97. }
  98. }
  99. void CWaveViewCtrl::OnLButtonDown( UINT nFlags, CPoint point )
  100. {
  101. CWnd::OnLButtonDown(nFlags,point );
  102. if(!m_MouseSel)return;
  103. if(m_selpoint!=-1)
  104. {
  105. m_selpoint=-1;
  106. OnPaint();
  107. }
  108. m_selpoint=point.x ;
  109. ::SetCaretPos(point.x,26);
  110. }
  111. void CWaveViewCtrl::OnMouseMove( UINT nFlags, CPoint point )
  112. {
  113. CWnd::OnMouseMove(nFlags,point );
  114. if(!m_MouseSel)return;
  115. int i=-1;
  116. if(nFlags==MK_LBUTTON &&m_selpoint!=-1)
  117. {
  118. CDC *dc=GetDC();
  119. CPoint old=GetCaretPos();
  120. CPen pe(PS_NULL,0,COLORREF(0));
  121. CPen* oldp =dc->SelectObject (&pe);
  122. dc->SetROP2(R2_NOT);
  123. if(point.x <old.x )
  124. if(!m_shiftcaret)
  125. {
  126. i=0;
  127. m_shiftcaret=true;
  128. }
  129. else
  130. i=1;
  131. if(point.x >old.x )
  132. if(m_shiftcaret)
  133. {
  134. i=0;
  135. m_shiftcaret=false;
  136. }
  137. else
  138. i=-1;
  139. if(point.x!=m_selpoint)
  140. {
  141. HideCaret();
  142. dc->Rectangle (old.x+i,26,point.x,rect.Width ()-26);
  143. ::SetCaretPos(point.x,26);
  144. ShowCaret();
  145. }
  146. else
  147. dc->Rectangle (m_selpoint+i,26,old.x,rect.Width ()-26);
  148. dc->SelectObject (oldp);
  149. ReleaseDC (dc);
  150. }
  151. }
  152. void CWaveViewCtrl::OnLButtonUp( UINT nFlags, CPoint point )
  153. {
  154. m_shiftcaret=false;
  155. }
  156. void CWaveViewCtrl::OnSize( UINT nType, int cx, int cy )
  157. {
  158. CRect rec;
  159. CPoint caret;
  160. caret=GetCaretPos();
  161. GetClientRect(&rec);
  162. if(m_selpoint!=-1)
  163. {
  164. TRACE("%d",m_selpoint);
  165. int pre1=(int)(((float)m_selpoint/rect.Width ())*100);
  166. m_selpoint=(int)((((float)rec.Width()*pre1)/100)+1);
  167. }
  168. int pre=(int)(((float)caret.x/rect.Width ())*100);
  169. int pos=(int)((float)(rec.Width()*pre)/100);
  170. rect=rec;
  171. if(isComm)
  172. {
  173. CreateCaret(true);
  174. ::SetCaretPos(pos+1,26);
  175. ShowCaret();
  176. }
  177. CWnd::OnSize (nType,rect.Width (),rect.Height());
  178. }
  179. //*******************************
  180. //<<<<<<<<<<<Implimentations>>>>>>>>>>>>>>>>
  181. CWaveViewCtrl::~CWaveViewCtrl()
  182. {
  183. /*if(isComm) //for free memory
  184. VirtualFree(m_data,m_pRiff->Size,MEM_DECOMMIT);
  185. VirtualFree(m_data,m_pRiff->Size,MEM_RELEASE); */
  186. UnmapViewOfFile(lpvFile);
  187. isComm=!isComm;
  188. DestroyCaret();
  189. SelectObject(m_MDC.GetSafeHdc (),m_pOldBitmap);
  190. if(DSound!=NULL)
  191. {
  192. if(DSoundBuff)
  193. DSoundBuff->Release ();
  194. DSound->Release() ;
  195. // DSound=NULL;DSoundBuff=NULL;
  196. }
  197. }
  198. void CWaveViewCtrl::OnPaint()
  199. {
  200. CPaintDC DC(this);
  201. if(isComm==false) return;
  202. /*::fch=fch;
  203. ::Riff=Riff;
  204. ::m_data =m_data;
  205. ::pDC=&m_MDC;
  206. ::hBitmap=&m_bitmap;
  207. ::hOldBitmap=m_pBitmap;
  208. ::memrect=&memrec;*/
  209. DrawTimeRuler(&DC);
  210. if (m_MDC.m_hDC ==NULL)
  211. {
  212. AfxBeginThread(DrawThread,(LPVOID)this);
  213. }
  214. else
  215. DrawThread((LPVOID)this);
  216. if(m_selpoint!=-1)
  217. OnMouseMove( MK_LBUTTON, CPoint(m_selpoint,0) );
  218. }
  219. void CWaveViewCtrl::DrawTimeRuler(CPaintDC* PaintDC)
  220. {
  221. CFont font,*oldf;
  222. int sp=rect.Width ()/10;
  223. int w=sp-sp/2;
  224. font.CreateFont((int)(w*0.33),w/8,0,0,FW_BOLD,1,0,0,0,1,OUT_DEFAULT_PRECIS,PROOF_QUALITY,FF_ROMAN,NULL );
  225. oldf=PaintDC->SelectObject(&font);
  226. int ss=(m_pRiff->Size/m_pfch->awAvgBytesPerSec)/10;
  227. ss=ss==0?ss=1:ss;
  228. int sc=0;
  229. for(int i=0 ;i<=10;i++)
  230. {
  231. int r=sp*i;
  232. PaintDC->Rectangle(r,25,r+1,12);
  233. int t[3];
  234. t[1]=sc/60;
  235. t[2]=t[1]/60;
  236. t[1]=t[1]-(t[2]*60);
  237. t[0]=sc-(t[2]*60+t[1])*60;
  238. char str[]="        ";
  239. for(int j=0;j<=2;j++)
  240. {
  241. char a[2];
  242. itoa(t[j],a,10);
  243. if(t[j]<=9)
  244. {
  245. a[1]=a[0];
  246. a[0]='0';
  247. }
  248. memcpy(&str[6-(j*3)],a,sizeof(char)*2);
  249. }
  250. str[2]=str[5]=':';
  251. PaintDC->TextOut(r,0,str,8);
  252. sc+=ss;
  253. }
  254. PaintDC->SelectObject(oldf);
  255. }
  256. void CWaveViewCtrl::Command(bool state)
  257. {
  258. if(!isComm)
  259. return;
  260. HRESULT hr;
  261. CLSID clsid;
  262. IUnknown *pUnk;
  263. IClassFactory *pclsf;
  264. DSBUFFERDESC Buffer;
  265. WAVEFORMATEX WavFmt;
  266. if(DSound==NULL)
  267. {
  268. if((hr=::CLSIDFromProgID(L"DirectSound",&clsid))!=NOERROR)
  269. {
  270. MessageBeep(MB_OK);
  271. return;
  272. }
  273. if((hr=::CoGetClassObject(clsid,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pclsf))!=
  274. NOERROR)
  275. {
  276. MessageBeep(MB_OK);
  277. return;
  278. }
  279. if(pclsf->CreateInstance(NULL,IID_IUnknown,(void**)&pUnk)!=S_OK)
  280. {
  281. MessageBeep(MB_OK);
  282. return;
  283. }
  284. if(pUnk->QueryInterface(IID_DirectSound,(void **)&DSound)!=S_OK)
  285. {
  286. MessageBeep(MB_OK);
  287. return;
  288. }
  289. pclsf->Release();
  290. pUnk->Release ();
  291. }
  292. if(DSoundBuff==NULL)
  293. {
  294. DSound->Initialize(NULL);
  295. DSound->SetCooperativeLevel (GetSafeHwnd(),DSSCL_NORMAL );
  296. memset(&Buffer,0,sizeof(Buffer));
  297. Buffer.dwSize =sizeof(Buffer);
  298. Buffer.dwFlags =DSBCAPS_CTRLDEFAULT;
  299. Buffer.dwBufferBytes= m_pRiff->Size ;
  300. memcpy((void*)&WavFmt,(void*)m_pfch,sizeof(*m_pfch));
  301. WavFmt.cbSize =0;
  302. Buffer.lpwfxFormat=&WavFmt;
  303. if((hr=DSound->CreateSoundBuffer (&Buffer,&DSoundBuff,NULL))!=DS_OK)
  304. return;
  305. LPVOID buff1,buff2;
  306. DWORD size1,size2;
  307. DSoundBuff->Lock (0,Buffer.dwBufferBytes,&((LPVOID)buff1),&size1,&((LPVOID)buff2),&size2,0);
  308. memcpy((void*)buff1,m_data,Buffer.dwBufferBytes );
  309. DSoundBuff->Unlock (buff1,size1,buff2,size2);
  310. }
  311. if(DSoundBuff)
  312. {
  313. DWORD stat;
  314. DSoundBuff->GetStatus (&stat);
  315. if(stat!=DSBSTATUS_PLAYING&&state)
  316. {
  317. CPoint caret=GetCaretPos();
  318. m_PBP.x=caret.x;
  319. m_PBP.y=m_selpoint;
  320. if(m_selpoint<caret.x)
  321. caret.x=m_selpoint;
  322. OnLButtonDown( 1, CPoint(0,0) );
  323. m_MouseSel=false;
  324. int pre=(int)(((float)caret.x/rect.Width ())*100);
  325. int pos=(int)((float)(m_pRiff->Size*pre)/100);
  326. DSoundBuff->SetCurrentPosition(pos);
  327. DSoundBuff->Play (0,0,0);
  328. TimerID=SetTimer(1,1,NULL);
  329. }else
  330. if(!state)
  331. DSoundBuff->Stop();
  332. }
  333. }
  334. void CWaveViewCtrl::CreateCaret(bool Flag)
  335. {
  336. if(Flag==true)
  337. {
  338. ::CreateCaret(GetSafeHwnd(),NULL,0,rect.Height ());
  339. ShowCaret();
  340. }
  341. else
  342. DestroyCaret();
  343. }
  344. void CWaveViewCtrl::OnSetFocus( CWnd* pOldWnd )
  345. {
  346. if(isComm)
  347. CreateCaret(true);
  348. }
  349. void CWaveViewCtrl::OnKillFocus( CWnd* pNewWnd )
  350. {
  351. if(isComm)
  352. CreateCaret(false);
  353. }
  354. //*************************************************
  355. //<<<<<<<<<<<<<<<<<Thread>>>>>>>>>>>>>>>>>>>>>
  356. UINT DrawThread(LPVOID pParam){
  357. CWaveViewCtrl* pWnd=(CWaveViewCtrl*)pParam;
  358. HWND hWnd =pWnd->GetSafeHwnd();
  359. if(pWnd->m_MDC.m_hDC ==NULL)  // we will draw wave for frist time 
  360. {
  361. CPen pen,*oldpen;
  362. //hBitmap=m_bitmap;//new CBitmap(); // create new bitmap
  363. pWnd->m_MDC.CreateCompatibleDC (NULL); // create memory DC compatible with system display
  364. pWnd->GetClientRect(&(pWnd->memrec)); // get the borders of the window that will display the wave
  365. pWnd->m_bitmap.CreateCompatibleBitmap(CDC::FromHandle (GetDC(hWnd)),pWnd->memrec.Width (),pWnd->memrec.Height ());
  366. pWnd->m_pOldBitmap =(CBitmap*)SelectObject(pWnd->m_MDC.GetSafeHdc (),pWnd->m_bitmap);
  367. pWnd->m_MDC.Rectangle (0,0,pWnd->memrec.Width (),pWnd->memrec.Height ());
  368. pen.CreatePen (PS_SOLID,0,RGB(0,90,180));
  369. oldpen=pWnd->m_MDC.SelectObject (&pen);
  370. DWORD size;
  371. size=pWnd->m_pfch->wBitsPerSample ==16?pWnd->m_pRiff->Size/2:pWnd->m_pRiff->Size;
  372. int b=0;
  373. int time=pWnd->m_pRiff->Size/pWnd->m_pfch->awAvgBytesPerSec ; // calcualte the time of the wave
  374. b=time<10 ? pWnd->memrec.Width()-((pWnd->memrec.Width()/10)*time):0;// if the time<10 calculate the wave width
  375. int pps=(pWnd->memrec.Width ()*15)/time; // calculate how many pixles per scond
  376. int n= pWnd->m_pfch->dwSamplesPerSec /pps;     // calculate the number of escapes
  377. int yy=pWnd->memrec.Height ()/4; // calculate the y of the first channel 
  378. pWnd->m_MDC.MoveTo (0,yy); // move to the orgin
  379. int h=yy; // calculate the hight of the first channel 
  380. short sample;
  381. for(int register x=0;x<(long)size;x=x+n) //to draw first channel
  382. {
  383. sample=pWnd->m_pfch->wBitsPerSample ==8?( (*((BYTE*)pWnd->m_data+x)-128)*h)/128:((*((short*)pWnd->m_data+x))*h)/(65535/2);
  384. pWnd->m_MDC.LineTo (int(((float)x/size)*(pWnd->memrec.Width()-b)),yy-sample);
  385. }
  386. yy= yy+h+h/2;
  387. pWnd->m_MDC.MoveTo (0,yy);
  388. if(pWnd->m_pfch->wChannels>1) // go here if the wave is stereo
  389. for( x=1;x<=(long)size;x=x+n) // to draw the scond channel
  390. {
  391. sample=pWnd->m_pfch->wBitsPerSample ==8?( (*((BYTE*)pWnd->m_data+x)-128)*h)/128:((*((short*)pWnd->m_data+x))*h)/(65535/2);
  392. pWnd->m_MDC.LineTo (int(((float)x/size)*(pWnd->memrec.Width()-b)),yy-sample);
  393. }
  394. pWnd->m_MDC.SelectObject (oldpen);
  395. }
  396. CRect rc;
  397. GetClientRect(hWnd,&rc);
  398. StretchBlt(GetDC(hWnd),0,25,rc.Width (),rc.Height (),pWnd->m_MDC .GetSafeHdc(),0,0,pWnd->memrec.Width ()
  399. ,pWnd->memrec.Height(),SRCCOPY);
  400. return 0;
  401. }
  402. void CWaveViewCtrl::OnTimer( UINT nIDEvent )
  403. {
  404. DWORD stat;
  405. DSoundBuff->GetStatus (&stat);
  406. if(stat==DSBSTATUS_PLAYING)
  407. {
  408. DWORD ReadPos,WritePos;
  409. DSoundBuff->GetCurrentPosition (&ReadPos,&WritePos);
  410. int time=m_pRiff->Size /m_pfch->dwSamplesPerSec ; // calcualte the time of the wave
  411. int timepos=ReadPos/m_pfch->dwSamplesPerSec ;
  412. float pre=((float)timepos/time)*100+1;
  413. int pos=int((rect.Width()*pre)/100);
  414. if(m_PBP.x>m_PBP.y)
  415. {
  416. if(pos>=m_PBP.x&&m_PBP.x!=m_PBP.y)
  417. DSoundBuff->Stop();
  418. }
  419. else
  420. if(pos>=m_PBP.y&&m_PBP.x!=m_PBP.y)
  421. DSoundBuff->Stop();
  422. ::SetCaretPos(pos,26);
  423. }else
  424. {
  425. ::SetCaretPos(m_PBP.x,26);
  426. m_selpoint=m_PBP.y;
  427. m_MouseSel=true;
  428. OnMouseMove( MK_LBUTTON, CPoint(m_selpoint,0) );
  429. KillTimer(TimerID);
  430. m_MouseSel=true;
  431. }
  432. }
  433. //**************************************