用waveIn采集音频数据,保存到记录文件里。记录格式如下:
audioData=packed record
   lpdata:PChar;
   dwbufferlength:DWORD;
   dwbytesrecorded:DWORD;
   dwUser:DWORD;
   dwflags:DWORD;
   dwloops:DWORD;
   buffer : array [0..500] of byte;
end;
每次从文件里读取一个记录,并传给waveOutPrepareHeader时,就会提示参数不合法。读取文件代码如下:
var
   Header:PWaveHdr;
   file_size,CurRec:integer;
   ad:audioData;
   filename:string;
begin
    filename:='new.abc';
    AssignFile(WavFile,filename);
    reset(WavFile); }
    file_size:=filesize(wavFile);
    CurRec:=0;
    Header:=new(PWaveHdr);
    while CurRec < file_size do
    begin
        seek(wavFile,CurRec);
        inc(CurRec);
        read(wavFile,ad);
        Header.dwBufferLength:=ad.dwbufferlength;
        Header.dwBytesRecorded:=0;
        Header.dwUser:=ad.dwUser;
        Header.dwFlags:=ad.dwflags;
        Header.dwLoops:=0;
        Header.lpData:=pointer(@ad.buffer);        i:=waveOutPrepareHeader(HWaveOut^,Header,sizeof(Header));
        if i<>MMSYSERR_NOERROR then application.messagebox('Out Prepare error','error',mb_ok);
        i:=waveOutWrite(HWaveOut^,Header,sizeof(TWaveHdr));       
        if i<>MMSYSERR_NOERROR then application.messagebox('Wave out error','error',mb_ok);
    end;
end;问题:
这样保存音频数据是否正确,还有我用的这种播放音频数据的方法是否正确?问题应该怎样解决?
多谢各位了!!

解决方案 »

  1.   

    不用这么麻烦。你可以在文件开始的地方记录音频格式,如:
    PCMFOMAT: TWAVEFORMATEX =
       (wFormatTag: WAVE_FORMAT_PCM;
        nChannels: 1;
        nSamplesPerSec: 8000;
        nAvgBytesPerSec: 16000;
        nBlockAlign: 2;
        wBitsPerSample: 16;
        cbSize: 0;
        );然后后面就只记录采集到的音频数据(二进制),比如采集10秒钟记录一次(本例中采集10秒会有160000个Byte的数据)。回放的时候就先读出音频格式那个结构用于初始化WaveOut,然后再循环读出160000个Byte进行回放。另外存文件时可以加入压缩过程,然后读出数据解压后再进行回放。
      

  2.   

    谢谢clasj,按照你的提示,我只存储音频数据,确实简化很多,而且waveOutPrepareHeader没有问题了,但是waveOutWrite有问题,提示的错误还是MMSYSERR_INVALPARAM。看了其它的一些资料,参数设置应该没问题呀,不知道是哪里出错了?
    代码如下:
    //play audio button
    procedure TForm1.Button3Click(Sender: TObject);
    var
       Header:PWaveHdr;
       i,file_size:integer;
       wv_buffer: array of byte;
    begin
        file_size:=filesize(wavFile);
        Header:=new(PWaveHdr);
        setLength(wv_buffer,file_size);
        seek(wavfile,0);
        //读取音频数据/
        for i:=0 to file_size-1 do
        begin
           read(wavfile,wv_buffer[i]);
        end;        Header.dwBufferLength:=file_size;
            Header.dwBytesRecorded:=0;
            Header.dwUser:=0;
            Header.dwFlags:=2;//WHDR_BEGINLOOP or WHDR_ENDLOOP;
            Header.dwLoops:=0;
            Header.lpNext:=nil;
            Header.reserved:=0;
            Header.lpData:=pointer(wv_buffer);
            i:=waveOutPrepareHeader(HWaveOut^,Header,sizeof(TWavehdr));
            if i<>MMSYSERR_NOERROR then application.messagebox('Out Prepare error','error',mb_ok);        i:=waveOutWrite(HWaveOut^,Header,sizeof(PWaveHdr));
            if i<>MMSYSERR_NOERROR then application.messagebox('Wave out error','error',mb_ok);end;
      

  3.   

    这个我也不太清楚了,我以前都是用的ACM控件,里面有ACMWaveIn、ACMWaveOut,你可以去下一个,带源码,你看看它是怎么调用的。