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

📄 tcmwavetype.pas

📁 语音与识别技术包含很多C语言处理模块系统
💻 PAS
📖 第 1 页 / 共 3 页
字号:
          //开辟内存
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, MODSaveSize));
          SaveSize := MODSaveSize;           //要播放的音频数据的长度
       end
       else begin
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
          SaveSize := LoadMemSize;
       end;
       Try
         if Buf = NIL then
            raise EMMIO.Create('不能分配内存!');
         Try    //读取与写音频数据
           case tSave of
             CS_SAVE_PLAY:
                if mmioRead(Dhio, Buf, SaveSize) <> SaveSize then
                   raise EMMIO.Create('读取数据出错:可能文件已被破坏!');
             CS_SAVE_RECORD:
                if FileRead(TempFile, Buf^, SaveSize) <> SaveSize then
                   raise EMMIO.Create('读取数据出错:可能文件已被破坏!');
           end;
           if SaveSize <> mmioWrite(hio, Buf, SaveSize) then
              raise EMMIO.Create('写语音数据错误');
         Finally
           GloBalFreePtr(Buf);  //释放内存
           SendMessage(Application.MainForm.Handle, CM_SAVEPOSI, i, 0); 
         end;
       Finally
         FileClose(TempFile);   //关闭临时文件
       end;
    end;
  Finally
    mmioClose(hio, 0);          //关闭目标音频文件
  end;
  //发送保存完毕的消息
  SendMessage(Application.MainForm.Handle, CM_ENDSAVE, 0, 0);
end;

//***********************************************************************//
//                                                                       //
//   转换音频数据到文件                                                  //
//   参数:                                                               //
//       NewFileName    : 要保存的文件名                                 //
//       DataLength     : 转换前的音频数据的长度                         //
//       NewWaveFmt     : 新的波形格式                                   //
//       OldWaveFmt     : 旧的波形格式                                   //
//       Dhio           : 源音频文件名柄 ( 在放音状态下保存文件有效 )    //
//       ShowPoi        : 回调过程                                       //
//   返回值:                                                             //
//             新的音频长度                                              //
//                                                                       //
//***********************************************************************//
function Wave_Save_ConvertFile(const NewFileName: String; DataLength: LongInt;
         NewWaveFmt, OldWaveFmt: TWAVEFORMATEX; Dhio: HMMIO; ShowPoi: TWaveLoopNotifyEvent): LongInt;
var
  hio: HMMIO;           //音频文件句柄
  Buf: PChar;           //用于读取数据的缓冲区
  SaveBuf: PChar;
  ck: TMMCKINFO;        //音频信息结构
  SaveLoop: LongInt;    //循环读取数据的次数
  Length: LongInt;      //要保存数据的长度
  NewLength: LongInt;
  i, j: LongInt;
  MODSaveSize: LongInt; //最后一次数据的长度
  SaveSize: LongInt;    //要写入文件的数据的长度
begin
  i := DataLength div OldWaveFmt.nBlockAlign;           //音频块对齐方式
  //转换比例
  j := Trunc(NewWaveFmt.nSamplesPerSec / OldWaveFmt.nSamplesPerSec * i);
  Length := NewWaveFmt.nBlockAlign * j;         //新的音频数据的长度

  SaveLoop := DataLength DIV LoadMemSize;
  MODSaveSize := 0;
  if (DataLength MOD LoadMemSize) <> 0 then
  begin
     SaveLoop := SaveLoop + 1;
     MODSaveSize := DataLength MOD LoadMemSize;
  end;

  if FileExists(NewFileName) then  //删除已有的目标文件
     DeleteFile(NewFileName);

  //创建成一个新的音频文件                   创建             可读写
  hio := mmioOpen(PChar(NewFileName), NIL, MMIO_CREATE + MMIO_READWRITE);
  if hio = 0 then
    raise EMMIO.Create('无法创建文件');
  Try           //WAVE_FORMAT_PCM 自定义音频格式
    if NewWaveFmt.wFormatTag = WAVE_FORMAT_PCM then        //波形格式的大小
      ck.cksize := Length + 4 + 8 + SizeOf(NewWaveFmt) - 2 + 8
    else
      ck.cksize := Length + 4 + 8 + SizeOf(NewWaveFmt) + NewWaveFmt.cbSize + 8;

    ck.fccType := mmioStringToFOURCC('WAVE', 0);        //创建文件头
    if 0 <> mmioCreateChunk(hio, @ck, MMIO_CREATERIFF) then
       raise EMMIO.Create('建立文件头错误');
    ck.ckid := mmioStringToFOURCC('fmt', 0);            //创建 fmt 块
    if NewWaveFmt.wFormatTag = WAVE_FORMAT_PCM then
      ck.cksize := SizeOf(NewWaveFmt) - 2                  //fmt 块的大小
    else
      ck.cksize := SizeOf(NewWaveFmt) + NewWaveFmt.cbSize;

    if 0 <> mmioCreateChunk(hio, @ck, 0) then
       raise EMMIO.Create('建立 fmt 块错误');
    mmioWrite(hio, PChar(@NewWaveFmt), ck.cksize);

    ck.ckid := mmioStringToFOURCC('data', 0);           //创建 data 数据块
    ck.cksize := Length;
    if 0 <> mmioCreateChunk(hio, @ck, 0) then
       raise EMMIO.Create('建立 data 块错误');

    for i := 1 to SaveLoop do
    begin
       if (MODSaveSize <> 0) AND (i = SaveLoop) then
       begin
          //开辟内存
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, MODSaveSize));
          SaveSize := MODSaveSize;           //要转换的音频数据的长度
       end
       else begin
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
          SaveSize := LoadMemSize;
       end;
       Try
         if Buf = NIL then
            raise EMMIO.Create('不能分配内存!');
         Try    //读取与写音频数据
            if mmioRead(Dhio, Buf, SaveSize) <> SaveSize then
               raise EMMIO.Create('读取数据出错:可能文件已被破坏!');

            SaveBuf := NIL;
            //转换数据
            NewLength := ConvertWave(Buf, SaveSize, OldWaveFmt, SaveBuf, NewWaveFmt);
            if NewLength <= 0 then
               raise EMMIO.Create('语音格式转换错误');

            if NewLength <> mmioWrite(hio, SaveBuf, NewLength) then
               raise EMMIO.Create('写语音数据错误');
         Finally
//            GloBalFreePtr(SaveBuf);             //释放空间
            if Assigned(ShowPoi) then           //显示进度
               ShowPoi(WA_EN_OPENFILE, 100, 0, (70 DIV SaveLoop) * i + 20);
           ReallocMem(SaveBuf, 0);      //清除内存
           GloBalFreePtr(Buf);  //释放内存
//           Buf := NIL;
         end;
       Finally
       end;
    end;
  Finally
    mmioClose(hio, 0);          //关闭目标音频文件
  end;
  Result := Length;
end;

//***********************************************************************//
//                                                                       //
//   画局部音频数据的波形                                                //
//   参数:                                                               //
//       Flag           : 波形显示周期                                   //
//       Buf            : 音频数据                                       //
//       Length         : 音频数据的长度                                 //
//       DesCanvas      : 要显示波形的目标画布                           //
//       DH, DW         : 目标画布的工作区域的高度与宽度                 //
//       DesBitMap      : 画波形时用的非可视源位图对像                   //
//       DrawLineColor  : 画波形的颜色                                   //
//       DrawBackColor  : 画波形的背景颜色                               //
//       Draw           : 是否画波形                                     //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure DrawPartWave(const Flag: Integer; Buf: PChar; Length: LongInt;
          DesCanvas: TCanvas; DH, DW: SmallInt; DesBitMap: TBitMap;
          DrawLineColor, DrawBackColor: TColor; Draw: Boolean = True);
var
   i, j, k, lmax, lmin: LongInt;
   Max, Min: LongInt;
   X, Y: SmallInt;
begin
  with DesBitMap do     //初始化图像参数
  begin
     Width := DW;
     Height := DH;
     Canvas.Brush.Color := DrawBackColor;
     Canvas.Brush.Style := bsSolid;
     Canvas.Pen.Color := DrawLineColor;
     Canvas.Pen.Mode := pmCopy;
     Canvas.FillRect(Rect(0, 0, DW, DH));
  end;

  if ((Length = 0) Or (Buf = NIL)) then
  begin //清除
     BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
     Exit;
  end;
  Max := -32768;
  Min := 32767;
  for i := 0 to (Length div 2 -1 ) do   //取到最小值与最大值
  begin
     j := PCMInt(PChar(Buf) + i * 2)^;
     if j > Max then Max := j;
     if j < Min then Min := j;
  end;
  DrawMin := Min;
  DrawMax := Max;

  if Not Draw then
  begin
     Exit;
  end;

  Max := Max - Min;     //最大振幅
  DesBitMap.Canvas.MoveTo(0, DH div 2);
  j := 0;
  X := 0;
  lmax := 0;
  lmin := 32767;
  for i := 0 to ((Length) div 2 -1) do
  begin
     if j < (Flag - 1) then     //如果是在一个周期内
     begin
        INC(j);
     end
     else begin
       j := 0;
       X := X + 1;
       lmax := 0;
       lmin := 32767;
     end;
     if Max <> 0 then           //取音频数据转换在整数
        Y := Abs(PCMInt(PChar(buf) + i * 2)^ - Min) * DH div Max
     else
        Y := DH div 2;
     k := 0;
     if Y > lmax then
     begin
        lmax := Y;
        k := 1;
     end;
     if Y < lmin then
     begin
        lmin := Y;
        k := 1;
     end;
     if k = 1 then
        DesBitMap.Canvas.LineTo(X, Y);  //画线
     if X > DW then break;
  end;
  //图像复制                                                             拷贝
  BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
end;

//***********************************************************************//
//                                                                       //
//   画全部音频数据的波形                                                //
//   参数:                                                               //
//       Dw_Type        : 波形显示数据记录                               //
//       WaveMin        : 波形数据的最小值                               //
//       WaveMax        : 波形数据的最大值                               //
//       DrawLineColor  : 画波形的颜色                                   //
//       DrawBackColor  : 画波形的背景颜色                               //
//       Draw           : 是否画波形                                     //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure DrawAllWave(Dw_Type: TDrawWave_Type; var WaveMin, WaveMax: LongInt;
          DrawLineColor, DrawBackColor: TColor; Draw: Boolean = True);
var
   Buf: PChar;          
   i, Loop, j, k, lmax, lmin: LongInt;
   Max, Min: LongInt;
   X, Y: SmallInt;
   DrawLoop: LongInt;
   MODDrawSize: LongInt;
   LoadSize: LongInt;
   hFile: Integer;
begin
  Application.ProcessMessages;

  hFile := 0;

  DrawLoop := Dw_Type.Length DIV LoadMemSize;
  MODDrawSize := 0;
  if (Dw_Type.Length MOD LoadMemSize) <> 0 then
  begin
     DrawLoop := DrawLoop + 1;
     MODDrawSize := Dw_Type.Length MOD LoadMemSize;
  end;

  SendMessage(Application.MainForm.Handle, CM_BEGINDRAW, DrawLoop * 3, 0);

  with Dw_Type.DesBitMap do
  begin
     Width := Dw_Type.DW;
     Height := Dw_Type.DH;
     Canvas.Brush.Color := DrawBackColor;
     Canvas.Brush.Style := bsSolid;
     Canvas.Pen.Color := DrawLineColor;
     Canvas.Pen.Mode := pmCopy;
     Canvas.FillRect(Rect(0, 0, Dw_Type.DW, Dw_Type.DH));
  end;

  if Dw_Type.Length = 0 then
  begin
     BitBlt(Dw_Type.DesCanvas.Handle, 0, 0, Dw_Type.DW, Dw_Type.DH,
            Dw_Type.DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
     Exit;
  end;

  case Dw_Type.FileType of      //不同的方式,打开不同的文件
                        //移到文件音频数据开始处
    CS_SAVE_PLAY:       mmioSeek(Dw_Type.hio, Dw_Type.Length, SEEK_END);  //播方方式
    CS_SAVE_RECORD:     hFile := FileOpen(Dw_Type.FileName, fmOpenRead);  //录音方式
  end;

  Max := -32768;
  Min := 32767;

  Try
    for Loop := 1 to DrawLoop do
    begin

⌨️ 快捷键说明

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