delphi2007 教程

delphi2007 教程

首页 新随笔 联系 聚合 管理
  1013 Posts :: 0 Stories :: 28 Comments :: 0 Trackbacks
录音时,显示即时播形图,求助 Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiMultimedia/html/delphi_20061106094422173.html
我想在录音的时候,同时显示出对应的波形数据,我用的是waveinstart系列函数,但是最终生成的wave文件中,并没有声音,用千千静听播放时,全是杂音,而且千千静听显示的波形很怪。我用的是如下方法生成wave文件头的。  
  procedure   TRecorder.WriteHead;  
  var  
      fmtSize:   Integer;  
      fileSize:   DWORD;  
       
      wf   :   file   of   TWavHeader;  
      wh   :   TWavHeader;  
  begin  
      wh.rId   :=   $46464952;  
      wh.rLen   :=   36   +   m_SumData;  
      wh.wId   :=   $45564157;  
      wh.fId   :=   $20746d66;  
      wh.fLen   :=   16;  
      wh.wFormatTag   :=   1;  
      wh.nChannels   :=   m_WaveFormat.nChannels;  
      wh.nSamplesPerSec   :=   m_WaveFormat.nSamplesPerSec;  
      wh.nAvgBytesPerSec   :=   m_WaveFormat.nAvgBytesPerSec;  
      wh.nBlockAlign   :=   m_WaveFormat.nBlockAlign;  
      wh.wBitsPerSample   :=   m_WaveFormat.wBitsPerSample;  
      wh.dId   :=   $61746164;  
      wh.wSampleLength   :=   m_SumData;  
   
      FileStream.Write(wh,   SizeOf(wh));  
  end;  
   
  其他代码即如下:  
   
   
   
   
  constructor   TRecorder.Create(wBitsPerSample,   wChannels:   Word;  
      dwSampleRate:   Cardinal;   nBufferLength:   Integer);  
  var  
      i:   Integer;  
  begin  
  m_bRecording   :=   FALSE;  
  m_bDeviceOpen   :=   FALSE;  
  m_PcmFormat.wBitsPerSample   :=   wBitsPerSample;  
  m_PcmFormat.wChannels   :=   wChannels;  
  m_PcmFormat.dwSampleRate   :=   dwSampleRate;  
  m_dwBufferSize   :=   (nBufferLength   *   (m_PcmFormat.wChannels)   *   (m_PcmFormat.wBitsPerSample)   div   8);  
  fnProcessBuffer   :=   nil;  
  m_lpWaveHdr   :=   nil;  
      m_SumData   :=   0;  
  m_hEvent   :=   0;  
  m_hThread   :=   0;  
      for   i:=   0   to   MAXNUMOFBUFFER   -   1   do  
  begin  
  m_hWaveInHdr[i]   :=   0;  
  m_hInBuffer[i]   :=   0;  
  end;  
  end;  
   
  constructor   TRecorder.Create(nBufferLength:   Integer);  
  var  
      i:   Integer;  
  begin  
      m_bRecording   :=   False;  
      m_bDeviceOpen   :=   False;  
      m_PcmFormat.wBitsPerSample   :=   16;  
      m_PcmFormat.wChannels   :=   2;  
      m_PcmFormat.dwSampleRate   :=   11025;  
      m_dwBufferSize   :=   (nBufferLength   *   m_PcmFormat.wChannels   *   m_PcmFormat.wBitsPerSample   div   8);  
  fnProcessBuffer   :=   nil;  
  m_lpWaveHdr   :=   nil;  
   
  m_hEvent   :=   0;  
  m_hThread   :=   0;  
      for   i:=   0   to   MAXNUMOFBUFFER   -   1   do  
  begin  
  m_hWaveInHdr[i]   :=   0;  
  m_hInBuffer[i]   :=   0;  
  end;  
  end;  
   
  constructor   TRecorder.Create(pcm:   TPCMFormat;   nBufferLength:   Integer);  
  var  
      i:   Integer;  
  begin  
  m_bRecording   :=   FALSE;  
  m_bDeviceOpen   :=   FALSE;  
  m_PcmFormat.wBitsPerSample   :=   pcm.wBitsPerSample;  
  m_PcmFormat.wChannels   :=   pcm.wChannels;  
  m_PcmFormat.dwSampleRate   :=   pcm.dwSampleRate;  
  m_dwBufferSize   :=   (nBufferLength   *   m_PcmFormat.wChannels   *   m_PcmFormat.wBitsPerSample   div   8);  
  fnProcessBuffer   :=   nil;  
  m_lpWaveHdr   :=   nil;  
   
  m_hEvent   :=   0;  
  m_hThread   :=   0;  
      for   i:=   0   to   MAXNUMOFBUFFER   -   1   do  
      begin  
  m_hWaveInHdr[i]   :=   0;  
  m_hInBuffer[i]   :=   0;  
      end;  
   
  end;  
   
   
  function   TRecorder.GetPosition:   Int64;  
  var  
      mmtime:   TMMTime;  
  begin  
      if   m_hWaveIn   <>   0   then  
      begin  
          mmtime.wType   :=   TIME_SAMPLES;  
          if   waveInGetPosition(m_hWaveIn,   @mmTime,   SizeOf(mmTime))   <>   MMSYSERR_NOERROR   then  
              Result   :=   -1  
          else  
              Result   :=   mmTime.sample;  
      end;  
      Result   :=   -1;  
  end;  
   
  function   TRecorder.IsDeviceOpen:   Boolean;  
  begin  
      Result   :=   m_bDeviceOpen;  
  end;  
   
  function   TRecorder.IsFormatSupported(wfEX:   tWAVEFORMATEX;  
      nDev:   Cardinal):   Boolean;  
  var  
      mm:   MMRESULT;  
  begin  
      mm   :=   waveInOpen(nil,   nDev,   @wfEx,   0,   0,   WAVE_FORMAT_QUERY);  
      if   mm   =   MMSYSERR_NOERROR   then  
          Result   :=   True  
      else  
          Result   :=   False;  
  end;  
   
  function   TRecorder.IsRecording:   Boolean;  
  begin  
      Result   :=   m_bRecording;  
  end;  
   
  procedure   TRecorder.Open(dwCallBack,   dwCallbackType:   Cardinal;  
      wMCIDeviceID:   MCIDEVICEID);  
  var  
      i:   Integer;  
  begin  
      if   not   m_bDeviceOpen   then  
      begin  
          if   dwCallBack   =   0   then  
              dwCallBack   :=   DWord(@waveinProc);  
   
          for   i:=   0   to   MAXNUMOFBUFFER   -   1   do  
          begin  
              m_hWaveInHdr[i]   :=   GlobalAlloc(GHND   or   GMEM_SHARE,   SizeOf(TWaveHdr));  
              m_lpWaveInHdr[i]   :=   pWaveHdr(GlobalLock(m_hWaveInHdr[i]));  
              m_hInBuffer[i]   :=   GlobalAlloc(GHND   or   GMEM_SHARE   ,   m_dwBufferSize);  
              m_lpInBuffer[i]   :=   PBYTE(GlobalLock(m_hInBuffer[i]));  
              m_lpWaveInHdr[i]^.lpData   :=   PChar(m_lpInBuffer[i]);  
              m_lpWaveInHdr[i]^.dwBufferLength   :=   m_dwBufferSize;  
              m_lpWaveInHdr[i]^.dwBytesRecorded   :=   0;  
              m_lpWaveInHdr[i]^.dwUser   :=   Cardinal(Pointer(Self));  
              m_lpWaveInHdr[i]^.dwFlags   :=   0;  
              m_lpWaveInHdr[i]^.dwLoops   :=   1;  
              m_lpWaveInHdr[i]^.lpNext   :=   nil;  
              m_lpWaveInHdr[i]^.reserved   :=   0;  
          end;  
   
          m_WaveFormat.wFormatTag   :=   WAVE_FORMAT_PCM;  
          m_WaveFormat.nChannels   :=   m_PcmFormat.wChannels;  
          m_WaveFormat.wBitsPerSample   :=   m_PcmFormat.wBitsPerSample;  
          m_WaveFormat.nSamplesPerSec   :=   m_PcmFormat.dwSampleRate;  
          m_WaveFormat.nBlockAlign   :=   m_WaveFormat.nChannels   *   m_WaveFormat.wBitsPerSample   div   8;  
          m_WaveFormat.nAvgBytesPerSec   :=   m_WaveFormat.nBlockAlign   *   m_WaveFormat.nSamplesPerSec;  
          m_waveClass.lpData   :=   Self;  
   
          if   not   ((waveInOpen(PHWAVEIN(@m_waveClass),   wMCIDeviceID,   PWaveFormatEx(@m_WaveFormat),  
                                              dwCallBack,   0,   dwCallbackType)   <>   0)   or  
                        (m_waveClass.hWave   =   0)  
                        )   then  
          begin  
              m_waveClass.lpData   :=   Self;  
              m_hWaveIn   :=   HWAVEIN(m_waveClass.hWave);  
              m_hEvent   :=   CreateEvent(nil,   False,   False,   nil);  
              m_bDeviceOpen   :=   True;  
          end;  
      end;  
  end;  
   
  function   TRecorder.Pause:   Boolean;  
  begin  
      Result   :=   False;  
      if   m_hWaveIn   <>   0   then  
      begin  
          if   waveInStop(m_hWaveIn)   =   MMSYSERR_NOERROR   then  
          begin  
              m_bRecording   :=   False;  
              Result   :=   True;  
          end;  
      end;  
  end;  
   
  procedure   TRecorder.ProcessNextBuffer(pwh:   PWaveHdr);  
  begin  
      if   @fnProcessBuffer   <>   nil   then  
          fnProcessBuffer(m_lpData,pwh);  
      m_SumData   :=   m_SumData   +   2048   -1;  
  waveInUnprepareHeader(m_hWaveIn,   pwh,   sizeof(WAVEHDR));  
  waveInPrepareHeader   (m_hWaveIn,   pwh,   sizeof(WAVEHDR));  
  waveInAddBuffer(m_hWaveIn,   pwh,   sizeof(WAVEHDR));  
  end;  
   
  procedure   TRecorder.SetBufferFunction(lpData:   Pointer;  
      fnProcess:   ProcessBuffer);  
  begin  
      m_lpData   :=   lpData;  
      fnProcessBuffer   :=   fnProcess;  
  end;  
   
  procedure   TRecorder.SetFormat(lpPcmFormat:   pPCMFormat);  
  begin  
      if   m_bDeviceOpen   =   False   then  
      begin  
          m_PcmFormat.wBitsPerSample   :=   lpPcmFormat^.wBitsPerSample;  
          m_PcmFormat.wChannels   :=   lpPcmFormat^.wChannels;  
          m_PcmFormat.dwSampleRate   :=   lpPcmFormat^.dwSampleRate;  
      end;  
  end;  
   
  procedure   TRecorder.SetFormat(wBitsPerSample,   wChannels:   Word;  
      dwSampleRate:   Cardinal);  
  begin  
  if   m_bDeviceOpen   =   False   then  
      begin  
          m_PcmFormat.wBitsPerSample   :=   wBitsPerSample;  
          m_PcmFormat.wChannels   :=   wChannels;  
          m_PcmFormat.dwSampleRate   :=   dwSampleRate;  
      end;  
  end;  
   
  procedure   TRecorder.Start;  
  var  
      i:   Integer;  
      ThreadId:   DWORD;  
  begin  
      if   not   m_bDeviceOpen     then  
          Exit  
      else  
      begin  
          for   i:=   0   to   MAXNUMOFBUFFER   -   1   do  
          begin  
              if   waveInPrepareHeader(m_hWaveIn,   m_lpWaveInHdr[i],   SizeOf(TWaveHdr))   <>   MMSYSERR_NOERROR   then  
                  Exit;  
              if   waveInAddBuffer(m_hWaveIn,   m_lpWaveInHdr[i],   SizeOf(TWaveHdr))   <>   MMSYSERR_NOERROR   then  
                  Exit;  
          end;  
          FileStream   :=   TFileStream.Create('c:\wave.wav',   fmCreate   or   fmOpenReadWrite   );  
          WriteHead;  
          //begin   sampling  
          m_bRecording   :=   True;  
          m_hThread   :=   CreateThread(nil,   0,   @RecorderThreadFunc,   Self,   0,   ThreadId);  
          waveInStart(m_hWaveIn);  
          if   m_hThread   <>   0   then  
          begin  
              SetPriorityClass(m_hThread,   REALTIME_PRIORITY_CLASS);  
              SetThreadPriority(m_hThread,   THREAD_PRIORITY_HIGHEST);  
          end;  
      end;  
  end;  
   
  procedure   TRecorder.Stop;  
  begin  
      if   (m_bDeviceOpen   =   False)   or   (m_bRecording   =   False)   then  
          Exit;  
      if   (waveInStop(m_hWaveIn))   <>   MMSYSERR_NOERROR   then  
          Exit  
      else  
          m_bRecording   :=   False;  
  end;  
   
   
   
   
  求高手与熟手指点下啊。如果哪位有代码请帮下俺啊。在线等,很急。  
 

剩下的代码:  
  procedure   TRecorder.Close;  
  var  
      i:   Integer;  
  begin  
      FileStream.Position   :=   0;     //重定位  
      WriteHead;  
      if   m_bRecording   then  
          Stop;  
      if   m_hThread   <>   0   then  
          CloseHandle(m_hThread);  
      if   m_bDeviceOpen   then  
          waveInClose(m_hWaveIn);  
   
      for   i:=   0   to   MAXNUMOFBUFFER-1   do  
      begin  
          if   (m_hWaveInHdr[i]   <>   0   )   then  
          begin  
              if   GlobalUnlock(m_hWaveInHdr[i])   then  
                  GlobalFree(m_hWaveInHdr[i]);  
              if   GlobalUnlock(m_hInBuffer[i])   then  
                  GlobalFree(m_hInBuffer[i]);  
              m_hWaveInHdr[i]   :=   0;  
              m_hInBuffer[i]   :=   0;  
          end;  
      end;  
   
      m_bDeviceOpen   :=   False;  
      m_bRecording   :=   False;  
      m_hThread   :=   0;  
  end;  
   
  function   TRecorder.Continue:   Boolean;  
  begin  
      Result   :=   False;  
      if   m_hWaveIn   <>   0   then  
      begin  
          if   waveInStart(m_hWaveIn)   =   MMSYSERR_NOERROR   then  
          begin  
              m_bRecording   :=   False;  
              Result   :=   True;  
          end;  
      end;  
  end;

好像没多少人有这么多工夫来检查这么多的代码。自己调试吧。哪出的问题,针对它查资料。

用Wave   Audio组件的TAudioRecorder(开源的)  
  就都不用自己写代码,呵呵~

这个组件可以实现吗????  
 

数据已实现出来了,请问哪位老大有显示波形图的函数啊。急啊

直接使用DirectX,对应数据话矩形,就可以搞定

posted on 2008-11-05 09:37 delphi2007 阅读(374) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。