⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tplaywaveunit.~pas

📁 语音与识别技术包含很多C语言处理模块系统
💻 ~PAS
📖 第 1 页 / 共 5 页
字号:
//***********************************************************************//
procedure TCMPlayWave.Copy(const StartPoi, Length: Integer);
var
  EditLength: LongInt;
  TempFile: Integer;
  Buf: PChar;
  LoopData, i: Integer;
  LoopMod: LongInt;
begin
  if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
     OR (StartPoi < 0) then
     Exit;
  EditLength := Length;
  if (StartPoi + Length) > LongInt(Self.DataLength) then
     EditLength := LongInt(Self.DataLength) - StartPoi;
  if EditLength <= 0 then
     Exit;

  //发送开始复制的消息
  SendMessage(Application.MainForm.Handle, CM_BEGINCOPY, 0, 0);
  if FileExists(Self.CopyDataFileName) then
     DeleteFile(Self.CopyDataFileName); //如果备份数据文件已存在

  LoopMod := LoadMemSize;
  LoopData := EditLength DIV LoadMemSize;
  if (EditLength MOD LoadMemSize) <> 0 then
  begin
     LoopMod := EditLength MOD LoadMemSize;
     LoopData := LoopData + 1;
  end;

  //发送数据处理长度消息
  SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, LoopData, 0);

  MMioSeek(Self.hio, LongInt(Self.DataLength) - StartPoi, SEEK_END);  //把文件指针移到音频数据的指定开始处
  //创建临时文件
  TempFile := FileCreate(Self.CopyDataFileName);

  Try
    Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
    if Buf = NIL then
       EMMIO.Create('不能分配内存');
    Try
      for i := 1 to LoopData - 1 do
      begin
        //读取指定长度的数据
        if mmioRead(Self.hio, Buf, LoadMemSize) <> LoadMemSize then
           raise EMMIO.Create('数据读取错误');
        FileWrite(TempFile, Buf^, LoadMemSize);    //写入临时文件中
        //发送数据处理长度消息
        SendMessage(Application.MainForm.Handle, CM_EDITPOI, i, 0);
      end;
    Finally
      GloBalFreePtr(Buf);
    end;
    if LoopMod > 0 then
    begin       //写余下的数据
       Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoopMod));
       if Buf = NIL then
          EMMIO.Create('不能分配内存');
       Try
         if mmioRead(Self.hio, Buf, LoopMod) <> LoopMod then
            raise EMMIO.Create('数据读取错误');
         FileWrite(TempFile, Buf^, LoopMod);
         SendMessage(Application.MainForm.Handle, CM_EDITPOI, LoopMod, 0);
       Finally
         GloBalFreePtr(Buf);
       end;
    end;
  Finally
    FileClose(TempFile);                  //关闭文件
  end;
  Self.PasteDataLength := EditLength;   //可用于粘贴的数据的长度
  //发送处理完毕的消息
  SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
end;

//***********************************************************************//
//                                                                       //
//   从指定位置删除指定长度的音频数据到剪贴板                            //
//   参数:                                                               //
//        StartPoi    : 删除音频数据的起始位置                           //
//        Length      : 音频数据的长度                                   //
//        DrawData    : 是否画波形                                       //
//   返回值:  无                                                         //
//                                                                       //
//***********************************************************************//
procedure TCMPlayWave.Delete(const StartPoi, Length: Integer; DrawData: Boolean);
var
  EditLength: LongInt;
  Dhio: HMMIO;
  ck: TMMCKINFO;
  i: Integer;
begin
  if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
     OR (StartPoi < 0) then
     Exit;
  EditLength := Length;
  if (StartPoi + Length) > LongInt(Self.DataLength) then
     EditLength := LongInt(Self.DataLength) - StartPoi;
  if EditLength <= 0 then
     Exit;

  //发送开始处理数据的消息
  SendMessage(Application.MainForm.Handle, CM_BEGINDEL, 0, 0);

  //确定数据要读取的次数
  i := EditLength DIV LoadMemSize;
  if (EditLength MOD LoadMemSize) <> 0 then
     INC(i);

  i := i + (LongInt(Self.DataLength) - (StartPoi + EditLength)) DIV LoadMemSize;
  if ((LongInt(Self.DataLength) - (StartPoi + EditLength)) MOD LoadMemSize) <> 0 then
     INC(i);

  //发送要编辑数据的长度消息
  SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, i + 2, 0);

  if FileExists(Self.CopyBackFileName) then
     DeleteFile(Self.CopyBackFileName);         //删除用于备份的文件

  //创建成一个新的音频文件                            创建          可读可写
  Dhio := mmioOpen(PChar(Self.CopyBackFileName), NIL, MMIO_CREATE + MMIO_READWRITE);
  if Dhio = 0 then
    raise EMMIO.Create('删除数据错');
  Try
    //波形格式的大小
    if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then
      ck.cksize := LongInt(Self.DataLength) - Length + 4 + 8 +
                   SizeOf(Self.pFormat^) - 2 + 8
    else
      ck.cksize := LongInt(Self.DataLength) - Length + 4 + 8 +
                   SizeOf(Self.pFormat^) + Self.pFormat^.cbSize + 8;

    ck.fccType := mmioStringToFOURCC('WAVE', 0);  //创建文件头
    if 0 <> mmioCreateChunk(Dhio, @ck, MMIO_CREATERIFF) then
       raise EMMIO.Create('删除数据错');
    ck.ckid := mmioStringToFOURCC('fmt', 0);;     //创建 fmt 块
    if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then
      ck.cksize := SizeOf(Self.pFormat^) - 2      //fmt 块的大小
    else
      ck.cksize := SizeOf(Self.pFormat^) + Self.pFormat^.cbSize;

    if 0 <> mmioCreateChunk(Dhio, @ck, 0) then
       raise EMMIO.Create('删除数据错');
    //写入音频格式到临时文件中
    mmioWrite(Dhio, PChar(Self.pFormat), ck.cksize);

    ck.ckid := mmioStringToFOURCC('data', 0);
    ck.cksize := LongInt(Self.DataLength) - Length;
    if 0 <> mmioCreateChunk(Dhio, @ck, 0) then    //创建 data 数据块
       raise EMMIO.Create('删除数据错');

    //发送处理数据进度的消息
    SendMessage(Application.MainForm.Handle, CM_EDITPOI, 1, 0);

    //把当前打开的音频文件的文件指针移到音频数据开始处
    mmioSeek(Self.hio, Self.DataLength, SEEK_END);

    Try
      Self.WriteWaveData(Dhio, StartPoi);       //写入数据
    Except
      mmioClose(Dhio, 0);                       //进行出错处理
      raise EMMIO.Create('删除数据错');
      Exit;
    end;

    //把文件指针从当前位置移到要删除数据的结尾处
    mmioSeek(Self.hio, Length, SEEK_CUR);

    Try         //写入数据
      Self.WriteWaveData(Dhio, LongInt(Self.DataLength) - (StartPoi + EditLength));
    Except
      mmioClose(Dhio, 0);
      raise EMMIO.Create('删除数据错');
      Exit;
    end;
  Finally
    mmioClose(Dhio, 0);
  end;

  mmioClose(Dhio, 0);   //关闭临时音频文件
  Self.Stop;
  Self.CloseWaveFile;   //关闭音频文件

  if FileExists(Self.UndoBackFileName) then
     DeleteFile(Self.UndoBackFileName); //删除当前用于撤消操作的备份文件         

  CopyFile(PChar(Self.BackFileName), PChar(Self.UndoBackFileName), TRUE);
  DeleteFile(Self.BackFileName);        //删除当前打开的音频备份文件

  //把临时文件复制成备份文件
  CopyFile(PChar(Self.CopyBackFileName), PChar(Self.BackFileName), TRUE);

  //发送处理进度消息
  SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);

  //打开备份文件
  if Self.OpenFileName(PChar(Self.BackFileName), DrawData) then
     Self.FNowPlay := CPSTOPING;

  Self.FCanUndo := TRUE;        //可以进行撤消操作
  SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0); //发送处理完毕的消息
end;

//***********************************************************************//
//                                                                       //
//   从指定位置剪切指定长度的音频数据到剪贴板                            //
//   参数:                                                               //
//        StartPoi    : 剪切音频数据的起始位置                           //
//        Length      : 音频数据的长度                                   //
//   返回值:  无                                                         //
//                                                                       //
//***********************************************************************//
procedure TCMPlayWave.Cut(const StartPoi, Length: Integer);
var
  EditLength: LongInt;
begin
  if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
     OR (StartPoi < 0) then
     Exit;                     
  EditLength := Length;
  if (StartPoi + Length) > LongInt(Self.DataLength) then
     EditLength := LongInt(Self.DataLength) - StartPoi;
  if EditLength <= 0 then
     Exit;

  //发送开始剪切的消息
  SendMessage(Application.MainForm.Handle, CM_BEGINCUT, 0, 0);
  Try
    Self.Copy(StartPoi, EditLength);    //复制数据
    Self.Delete(StartPoi, EditLength);  //删除数据
  Finally
    //处理完毕
    SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
  end;
end;

//***********************************************************************//
//                                                                       //
//   把从指定位置开始的指定长度的数据用剪切板中的数据覆盖掉              //
//   参数:                                                               //
//        StartPoi    : 要覆盖的音频数据的起始位置                       //
//        Length      : 要覆盖的音频数据的长度                           //
//        DrawData    : 是否画波形                                       //
//   返回值:  无                                                         //
//                                                                       //
//***********************************************************************//
procedure TCMPlayWave.Paste(const StartPoi, Length: LongInt; DrawData: Boolean);
var
  EditLength: LongInt;
  Dhio: HMMIO;
  ck: TMMCKINFO;
  TempFile: Integer;
  Buf: PChar;
  LoopData, i: Integer;
  LoopMod: LongInt;
begin
  if (StartPoi > LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING) OR
     (NOT Self.CanPaste) OR (StartPoi < 0) OR (Length < 0) then
     Exit;

  EditLength := Self.PasteDataLength;   //可用于粘贴的数据的长度
  if EditLength <= 0 then
     Exit;

  //发送开始粘贴数据的消息
  SendMessage(Application.MainForm.Handle, CM_BEGINPASTE, 0, 0);

  //删除数据
  Self.Delete(StartPoi, Length, False);

  i := EditLength DIV LoadMemSize;
  if (EditLength MOD LoadMemSize) <> 0 then
     INC(i);

  i := i + (LongInt(Self.DataLength) - (StartPoi + EditLength)) DIV LoadMemSize;
  if ((LongInt(Self.DataLength) - (StartPoi + EditLength)) MOD LoadMemSize) <> 0 then
     INC(i);

  //处理进度
  SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, i + 2, 0);

  //删除临时音频文件
  if FileExists(Self.CopyBackFileName) then
     DeleteFile(Self.CopyBackFileName);

  //新建临时音频文件
  Dhio := mmioOpen(PChar(Self.CopyBackFileName), NIL, MMIO_CREATE + MMIO_READWRITE);
  if Dhio = 0 then
    raise EMMIO.Create('粘贴数据错');
  Try   //创建音频文件的信息头
    if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then  //波形格式的大小
      ck.cksize := LongInt(Self.DataLength) + EditLength + 4 + 8 +
                   SizeOf(Self.pFormat^) - 2 + 8
    else
      ck.cksize := LongInt(Self.DataLength) + EditLength + 4 + 8 +
                   SizeOf(Self.pFormat^) + Self.pFormat^.cbSize + 8;

    ck.fccType := mmioStringToFOURCC('WAVE', 0);       //创建文件头
    if 0 <> mmioCreateChunk(Dhio, @ck, MMIO_CREATERIFF) then
       raise EMMIO.Create('粘贴数据错');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -