unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, mmsystem;type
  //GD = array of Char;
  TForm1 = class(TForm)
    Button1: TButton;
    EdtPhoneNum: TEdit;
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    wf : TWaveFormatEx;
   mmr : MMRESULT;
    Flag : Boolean;
    function  VoidOutInit() : Boolean;
    function GetWavLength(FileName : String): integer;
  public
    { Public declarations }
  end;var
  Form1: TForm1;
  WaveOutHandle : HWAVEOUT;
implementation{$R *.dfm}{ TForm1 }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 ); mmr := waveOutOpen(@WaveOutHandle,WAVE_MAPPER,@wf,self.Handle,0,CALLBACK_WINDOW);    if mmr <> MMSYSERR_NOERROR then
    begin
     result := false;
      exit;
    end;
    result := true ;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
  Flag := False;
end;procedure TForm1.Button1Click(Sender: TObject);
var ReadFile : file;
    Buf : PWaveHdr;
    //Temp : Array of GD;
    Temp : Array of PChar;
    //PlayBuffer : Array of Char;
    PlayBuffer : PChar;
    LenList : Array of integer;
    PhoneNum : Array of Char;
    NumRead, i, m, NumCount, BufLen, j,x: integer;
    str,FileName : String;begin
  NumRead := 0;
  BufLen := 0;
  NumCount :=0;
  x := 0;
  m := 0;
  if VoidOutInit = false then
  begin
     ListBox1.Items.Add('设备打开错误!');
     exit;
  end;
  str := EdtPhoneNum.Text;  if str <> '' then
  begin
    NumCount := length(str);
    SetLength(PhoneNum,NumCount);
    SetLength(Temp,NumCount);
    SetLength(LenList,NumCount);    for i := 0  to (NumCount - 1) do
    begin
      PhoneNum[i] := str[i+1];
      FileName := str[i+1] + '.wav';
      m := GetWavLength(FileName);
      LenList[i] := m;
      BufLen := BufLen + m;      //SetLength(Temp[i],m);
      GetMem(Temp[i],m + 1);
      ZeroMemory(Temp[i],m + 1);
      ShowMessage(inttostr(m));      AssignFile(ReadFile,FileName);
      Reset(ReadFile,1);
      Seek(ReadFile,44);
      BlockRead(ReadFile,Temp[i],m,NumRead);
      CloseFile(ReadFile);
    end;
  end;
  **//SetLength(PlayBuffer,BufLen);
  
  **GetMem(PlayBuffer,BufLen);
  ZeroMemory(PlayBuffer,BufLen);
  for i := 0 to (NumCount-1) do
  begin
    CopyMemory(PlayBuffer + x ,Temp[i],LenList[i]);    x := x + 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;  ASSERT(waveOutPrepareHeader(WaveOutHandle, Buf,sizeof(WAVEHDR) ) = MMSYSERR_NOERROR);
  ASSERT(waveOutWrite(WaveOutHandle ,Buf, sizeof(WAVEHDR) ) = MMSYSERR_NOERROR);
  //GetMem(FileBuf,7052);
  //ZeroMemory(FileBuf,7052);
  //CopyMemory(Buf.lpData,FileBuf+44,7008);
  //Buf.lpData := FileBuf + 44;//Temp + 44;
  {AssignFile(ReadFile,'1.wav');
  Reset(ReadFile,2);
  BlockRead(ReadFile,FileBuf,7052,NumRead);
  ASSERT(waveOutPrepareHeader(WaveOutHandle, Buf,sizeof(WAVEHDR) ) = MMSYSERR_NOERROR);
  ASSERT(waveOutWrite(WaveOutHandle ,Buf, sizeof(WAVEHDR) ) = MMSYSERR_NOERROR);
  CloseFile(ReadFile);   }
end;function TForm1.GetWavLength(FileName : String): integer;
var //Head : Array[0..43] of Char;
    ReadFile : file;
    NumRead, len ,i: integer;begin
  len := 0;
  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);
  Result := len;
end;end.
这个程序是想把录有0-9 10个数字的WAVE文件随意拼接后播放出来,在Edit控件中输入数字然后进行播放,现在我用开空间的方法和开动态数组的方法都有内存读写错误!但是不知道错误出在哪!注释掉的是用动态数组方法做的!出错的地方是打*的句子!还有就是我把动态数组的名称(就是数组首地址)赋给Buf.lpData为什么说类型不一样呢!要怎么解决呢?问题太多了!请各位专家指教!今天才发现内存操作学得太差了!谢谢大家!

解决方案 »

  1.   

    谢谢 FlyAnyWhere(有道无知) 一定给分,但是内存读写错误又什么什么原因呢?谢谢大家了!再帮帮忙吧!
      

  2.   

    真的就没有人会用FastReport吗?
    http://community.csdn.net/Expert/topic/3075/3075900.xml?temp=.5961267
      

  3.   

    晕了,看了半天才发现错误。Temp的声明是:
    Temp : Array of PChar;
    也就是每个元素都是指针,但你这里:
    BlockRead(ReadFile,Temp[i],m,NumRead);
    应该用Temp[i]^,好好看看帮助
      

  4.   

    对不起那个是我贴的时候改错了!应该是注释掉//Temp : Array of PChar;
    Temp : Array of GD;Temp是我定义的一个储存动态数组的动态数组
    GD = array of Char;要给它里面存的每一个动态数组定义长度该怎么样做呢比如这样可以吗?SetLength(Temp[i],100);在调用它里面的动态数组时应该怎么做呢?这样可以吗?
    Buf.lpData  := PChar(Temp);
    还是这样呢?
    Buf.lpData  := @Temp[i];我对Delphi中的动态数组不了解!谢谢各位大人!
      

  5.   

    定义成动态数组也要这么写:BlockRead(ReadFile,Temp[i]^,m,NumRead);
    动态数组实质上也是指针,这是向C学的。
    你说的其它的方面好像没问题
      

  6.   


    Temp : Array of PChar;
    Temp : Array of GD;
    SetLength(Temp[i],100);Temp[i]是表示指向谁的指针?Temp[i]^也是指针吗?指向谁的?Temp呢?有点糊涂了!谢谢NewStarSE(新星)大人了。
    请给详细说说在Delphi中的数组的指针!
      

  7.   

    对了还有比如Temp : Array of PChar
    SetLenght(Temp,100);GetMem(Temp[i],100);可以这样来空间吗?
    Temp[i]是表示的是一个PChar的值吗?
      

  8.   

    Temp : Array of PChar;----->Temp是动态数组,它的每一个元素是指针,所以这是一个指针型的动态数组
    Temp : Array of GD;-------->Temp是动态数组,它的每一个元素是仍然是动态数组,所以这是一个二维动态数组。和一般的二维数组不同的是,它每一行的元素数目不必相等SetLength(Temp[i],100);Temp[i]是表示指向谁的指针?---------->当然是指向你所申请的这片内存空间Temp[i]^也是指针吗?指向谁的?-------->它不再是指针,是Temp[i][0]这个元素,这里之所以要用BlockRead(ReadFile,Temp[i]^,m,NumRead);是因为BlockRead的原型是这样声明的:
    BlockRead(var F: File; var Buf; Count: Integer [; var AmtTransferred: Integer]);
    注意var Buf,这里说明Buf是任意类型的,所以随便写成什么样子都不会有编译错误,同时VAR表明它是传地址(引用)调用。(1)如果实参是指针变量,那么传过去的是这个变量所在的内存地址。(2)如果实参是静态数组的名字,那么传过去的就是这个数组的首地址。(3)如果实参是动态数组的名字,由于动态数组实质上就是指针,所以传过去的是动态数组名这个变量所在的内存地址,这和(1)是相同的,和(2)不同,所以调用的时候各不相同。(1)要用Temp[i]^,(2)要用Temp[i],(3)要用Temp[i][0]。
    用上面这个函数是很容易出错的。反正要记住一点:动态数组和指针实质上是同一个东西,只是使用的形式不同。例如:p:Pchar和t:array of char,那么p^<======>t[0],这和C中的指针与数组的关系一模一样。静态数组则完全不同。Temp呢?-------->你按上面那样声明,Temp就是一个二级指针后面理解对了。
      

  9.   

    谢谢~NewStarSE(新星)!希望今后能多帮忙!