unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, mmsystem, StdCtrls;type
  index = record
    name : String;
    start : integer;
    len : integer;
  end;
  TForm1 = class(TForm)
    EdtNum: TEdit;
    BtnPlay: TButton;
    ListBox1: TListBox;    procedure FormCreate(Sender: TObject);
    procedure BtnPlayClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Buf : PWaveHdr;
    wf : TWaveFormatEx;
  mmr : MMRESULT;
    NumCount ,BufLen : integer;    WavList : Array[0..9] of index;
    function  VoidOutInit() : Boolean;
    function GetWavLength(FileName : String): integer;
  public    { Public declarations }
  end;var
  Form1: TForm1;
  WaveOutHandle : HWAVEOUT;
  Enc : Array of PSmallint;
  Temp : PSmallint;
  Dec : Array of PChar;
  LenList : Array of Integer;
  PlayBuffer : PChar;
implementation
procedure dec_Init(buf : PSmallint; lenIn : integer; Data : PSmallint; lenOut : PInteger); StdCall; external 'yp.dll';
{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
begin
    WavList[0].name := '9';
    WavList[0].start := 0;
    WavList[0].len := 17;
    WavList[1].name := '1';
    WavList[1].start := 17;
    WavList[1].len := 10;
    WavList[2].name := '2';
    WavList[2].start := 27;
    WavList[2].len := 9;
    WavList[3].name := '3';
    WavList[3].start := 36;
    WavList[3].len := 14;
    WavList[4].name := '4';
    WavList[4].start := 50;
    WavList[4].len := 19;
    WavList[5].name := '5';
    WavList[5].start := 69;
    WavList[5].len := 20;
    WavList[6].name := '6';
    WavList[6].start := 89;
    WavList[6].len := 14;
    WavList[7].name := '7';
    WavList[7].start := 103;
    WavList[7].len := 17;
    WavList[8].name := '8';
    WavList[8].start := 120;
    WavList[8].len := 12;
    WavList[9].name := '0';
    WavList[9].start := 132;
    WavList[9].len := 13;
end;function TForm1.GetWavLength(FileName: String): integer;
var //Head : Array[0..43] of Char;
    ReadFile : file;
    NumRead, len : integer;
begin
  len := 0;
  try
    AssignFile(ReadFile,FileName);
    Reset(ReadFile,1);
    seek(ReadFile,40);
    //BlockRead(ReadFile,Head,44,NumRead);
    BlockRead(ReadFile,len,4,NumRead);
    //CopyMemory(@len,Head + 40,4);
    CloseFile(ReadFile);
  except
    ShowMessage('读取文件长度错误,请检查文件是否存在或是文件已经损坏!');
    result := 0;
    exit;
  end;
  Result := len;
end;function TForm1.VoidOutInit: Boolean;
begin
  wf.wFormatTag := WAVE_FORMAT_PCM;
wf.cbSize := 0;
wf.wBitsPerSample := 16;
wf.nSamplesPerSec := 16000;
wf.nChannels := 1;
wf.nAvgBytesPerSec := wf.nSamplesPerSec * ( wf.wBitsPerSample div 8 );
wf.nBlockAlign := wf.nChannels * ( wf.wBitsPerSample div 8 );
  try
 waveOutOpen(@WaveOutHandle,WAVE_MAPPER,@wf,self.Handle,0,CALLBACK_WINDOW);
  except
      ShowMessage('打开放音设备错误,请检查设备是否准备好!');
  result := false;
      exit;
  end;
    result := true ;
end;procedure TForm1.BtnPlayClick(Sender: TObject);
var  str : String;
  i , j, DecNum, EncNum, MovLen: integer;
  //PhoneNum : Array of String;  ReadFile, WriteFile : file;begin
  NumCount := 0;
  BufLen := 0;
  MovLen := 0;
  if VoidOutInit = false then
  begin
     ListBox1.Items.Add('设备打开错误!');
     exit;
  end;
  str := EdtNum.Text;
  NumCount := length(str);
  //SetLength(PhoneNum,NumCount);
  SetLength(Enc,NumCount);
  SetLength(Dec,NumCount);
  SetLength(LenList,NumCount);
  if str <> '' then
  begin
    for i := 0 to NumCount - 1 do
    begin
      for j := 0 to 9 do
      begin
        if WavList[j].name = str[i + 1] then
        begin
          GetMem(Enc,WavList[j].len * 22);
          ZeroMemory(Enc,WavList[j].len * 22);
          GetMem(Dec,WavList[j].len * 640);
          ZeroMemory(Dec,WavList[j].len * 640);
          GetMem(Temp,WavList[j].len * 640);
          ZeroMemory(Temp,WavList[j].len * 640);
          LenList[i] := WavList[j].len * 22;
          BufLen := BufLen + WavList[j].len * 640;
          AssignFile(ReadFile,'Speech.dat');
          Reset(ReadFile,2);
          Seek(ReadFile,WavList[j].start * 22);
          BlockRead(ReadFile,Enc[i]^,WavList[j].start * 22, EncNum);
          CloseFile(ReadFile);
          dec_Init(Enc[i],WavList[j].len * 11,Temp,@DecNum);
          CopyMemory(Dec[i],Temp,WavList[j].len * 640);
        end;
      end;
    end;  end
  else
  begin
    ShowMessage('请输入号码!');
    exit;
  end;
  GetMem(PlayBuffer,BufLen);
  ZeroMemory(PlayBuffer,BufLen);
  for i := 0 to  NumCount-1 do
  begin
    CopyMemory(PlayBuffer + MovLen,Dec[i],BufLen);    MovLen := MovLen + LenList[i];
  end;
  GetMem(Buf,sizeof(WaveHdr));
  ZeroMemory(Buf,sizeof(WaveHdr));
  //GetMem(Buf.lpData,BufLen);
  //ZeroMemory(Buf.lpData,BufLen);
  Buf.dwBufferLength := BufLen;
  Buf.dwFlags := 0;
  Buf.dwLoops := 0;
  Buf.lpData := PlayBuffer;
  try
    waveOutPrepareHeader(WaveOutHandle, Buf,sizeof(WAVEHDR));
    waveOutWrite(WaveOutHandle ,Buf, sizeof(WAVEHDR) );
  except
    ShowMessage('声音播放出错!');
    waveOutUnprepareHeader(WaveOutHandle,Buf,sizeof(WAVEHDR));
    waveOutClose(WaveOutHandle);
    //FreeMem(Buf);    for i := 0 to  NumCount-1 do
    begin
      FreeMem(Enc[i]);
      FreeMem(Dec[i]);    end;
    FreeMem(Temp);
    FreeMem(PlayBuffer);
    FreeMem(Buf);
    exit;
  end;
  
end;procedure TForm1.FormDestroy(Sender: TObject);
var i : integer;
begin
  i := 0;
  waveOutUnprepareHeader(WaveOutHandle,Buf,sizeof(WAVEHDR));
  waveOutClose(WaveOutHandle);
    //FreeMem(Buf);  for i := 0 to  NumCount-1 do
  begin
    FreeMem(Enc[i]);
    FreeMem(Dec[i]);  end;
  FreeMem(Temp);
  FreeMem(PlayBuffer);
  FreeMem(Buf);
end;end.
这个程序在执行到文件操作的时候会出I/O errors 998的错,还有在内存拷贝和退出的时候都有错!我水平不高 希望各位指点!
这个程序需要调用一个数据解压缩的DLL,哪位大人解答问题时需要的话请联系我 我用QQ传 我的QQ:34483703谢谢大家了!很急的!

解决方案 »

  1.   

    WavList[0].Len没有赋值
    还有建议你用类型文件操作
      

  2.   

    WavList[0].Len赋值了,在FormCreate里赋的,我觉得二进制数据是不是应该用无类型比较好!
      

  3.   

    高手们 帮我看看这贴子
    http://community.csdn.net/Expert/topic/3122/3122396.xml?temp=.728985
      

  4.   

    用PlaySound()函数就可以啊。。这个函数你看看:function TFormMain.PlaySnd():Boolean;
    var
    ResStream:TResourceStream;
      CpsBuf,DCpsBuf:Pointer;
      DeCompressSize:Integer;
    begin
    Result:=false;
    try
       ResStream:=TResourceStream.Create(hInstance,'Sound','Compress');
    GetMem(CpsBuf,ResStream.Size);
        ResStream.ReadBuffer(CpsBuf^,ResStream.Size);
        DecompressBuf(CpsBuf,ResStream.Size,0,DCpsBuf,DeCompressSize);
        if (PlaySound(DCpsBuf,hInstance,SND_ASYNC or SND_LOOP or SND_MEMORY)=true) then
         Result:=true;
      finally
       ResStream.Free;
      end;
    end;
    程序最后没有释放CpsBuf的内存,你将它做成全局的,程序结束时释放就可以了。。