我想在录音的时候,同时显示出对应的波形数据,我用的是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;
求高手与熟手指点下啊。如果哪位有代码请帮下俺啊。在线等,很急。

解决方案 »

  1.   

    剩下的代码:
    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;
      

  2.   

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

  3.   

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