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

📄 tcmwavetype.pas

📁 语音与识别技术包含很多C语言处理模块系统
💻 PAS
📖 第 1 页 / 共 3 页
字号:
       if (MODDrawSize <> 0) AND (Loop = DrawLoop) then
          LoadSize := MODDrawSize            //要播放的音频数据的长度
       else
          LoadSize := LoadMemSize;
       //开辟内存
       Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));

       if Buf = NIL then
          raise EMMIO.Create('不能分配内存!');

       Try
         case Dw_Type.FileType of       //读音频数
            CS_SAVE_PLAY:         mmioRead(Dw_Type.hio, Buf, LoadSize);
            CS_SAVE_RECORD:       FileRead(hFile, Buf^, LoadSize);
         end;

         if Dw_Type.Length <= LoadMemSize then  //假如小于区域长度的最大长度
         begin  //画区域波形
           DrawPartWave(Dw_Type.Flag, Buf, Dw_Type.Length, Dw_Type.DesCanvas,
                        Dw_Type.DH, Dw_Type.DW, Dw_Type.DesBitMap, DrawLineColor,
                        DrawBackColor, Draw);
           WaveMin := DrawMin;
           WaveMax := DrawMax;
           SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop * 3, 0);
           SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
           FileClose(hFile);
           Exit;
         end;

         for i := 0 to (LoadSize div 2 - 1) do
         begin          //取最大最小值
            j := PCMInt(PChar(Buf)+ i * 2)^;
            if j > Max then Max := j;
            if j < Min then Min := j;
         end;
       Finally
         GloBalFreePtr(Buf);
       end;
       SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop, 0);
    end;
  Finally
    FileClose(hFile);
  end;

  WaveMin := Min;
  WaveMax := Max;

  if Not Draw then
  begin
     if Dw_Type.FileType = CS_SAVE_RECORD then FileClose(hFile);
     SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
     Exit;
  end;

  Max := Max - Min;
  Dw_Type.DesBitMap.Canvas.MoveTo(0, Dw_Type.DH div 2);
  j := 0;
  X := 0;
  lmax := 0;
  lmin := 32767;

  hFile := 0;

  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);
  else
      hFile := 0;
  end;

  Try
    for Loop := 1 to DrawLoop do
    begin
      if (MODDrawSize <> 0) AND (Loop = DrawLoop) then
       begin
          //开辟内存
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, MODDrawSize));
          LoadSize := MODDrawSize;           //要播放的音频数据的长度
       end
       else begin
          Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
          LoadSize := LoadMemSize;
       end;

       if Buf = NIL then
          raise EMMIO.Create('不能分配内存!');

       Try
         case Dw_Type.FileType of
            CS_SAVE_PLAY:         mmioRead(Dw_Type.hio, Buf, LoadSize);
            CS_SAVE_RECORD:       FileRead(hFile, Buf^, LoadSize);
         end;
         for i := 0 to (LoadSize div 2 - 1 ) do
         begin
            if j < (Dw_Type.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) * Dw_Type.DH div Max
            else
               Y := Dw_Type.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
               Dw_Type.DesBitMap.Canvas.LineTo(X, Y);
            if X > Dw_Type.DW then break;
         end;
       Finally
          GloBalFreePtr(Buf);
       end;
       SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop + Loop * 2 , 0);
    end;
  Finally
     FileClose(hFile);
  end;

  //复制图像
  BitBlt(Dw_Type.DesCanvas.Handle, 0, 0, Dw_Type.DW, Dw_Type.DH,
         Dw_Type.DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
  SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
end;

//***********************************************************************//
//                                                                       //
//   画放音时的动态波形                                                  //
//   参数:                                                               //
//       Buf            : 音频数据指针                                   //
//       Length         : 音频数据的长度                                 //
//       DesCanvas      : 用来显示波形的目标画布                         //
//       DH, DW         : 目标画布工作区的高度与宽度                     //
//       Min, Max       : 音频数据的最小值与最大值                       //
//       DrawLineColor  : 画波形的颜色                                   //
//       DrawBackColor  : 画波形的背景颜色                               //
//       StartPoi       : 开始画波形的位置                               //
//       DrawLength     : 要画的波形的数据的长度                         //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure HawDrawWave(Buf: PChar; Length: LongInt; DesCanvas: TCanvas;
          DH, DW: SmallInt; Min, Max: LongInt; DrawLineColor, DrawBackColor: TColor;
          StartPoi: LongInt = 0; DrawLength: LongInt = 0);
Var
   i: LongInt;
   Y: SmallInt;
   DesBitMap: TBitMap;
begin
  DesBitMap := TBitMap.Create;

  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));
     Canvas.MoveTo(0, DH DIV 2);
     Canvas.LineTo(DW, DH DIV 2);
  end;

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

  if (StartPoi MOD 2) = 1 then
     StartPoi := StartPoi + 1;

  if StartPoi >= Length then
     StartPoi := 2;

  if DrawLength div 2 > DW then         //开始处
     DrawLength := DW * 2;

  if (StartPoi + DrawLength) > Length then
     DrawLength := Length - StartPoi;

  if DrawLength <= 0 then
     DrawLength := DW * 2;
                                            
  Max := Max - Min;
  for i := 0 to (DrawLength div 2 -1) do
  begin
     if Max <> 0 then
        Y := Abs(PCMInt(PChar(Buf) + StartPoi + i * 2)^ - Min) * DH div Max
     else
        Y := 0;

        Y := ABS(DH DIV 2 - Y);

        if Y >= (DH DIV 2) then
           continue;

        //画波形
        DesBitMap.Canvas.MoveTo(i, DH DIV 2 - Y);
        DesBitMap.Canvas.LineTo(i, DH DIV 2 + Y);

     if i > DW then break;
  end;
  //复制图像
  BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
  DesBitMap.Free;
end;

//***********************************************************************//
//                                                                       //
//   把指定格式的音频数据转换成另一种指定格式的音频数据                  //
//   参数:                                                               //
//       OldBuf           : 要转换的音频数据                             //
//       OldLen           : 转换前的音频数据的长度                       //
//       Newfmt           : 新的波形格式                                 //
//       Oldfmt           : 旧的波形格式                                 //
//       NewBuf           : 转换后的音频数据                             //
//   返回值:                                                             //
//             新的音频长度                                              //
//                                                                       //
//***********************************************************************//
function ConvertWave(OldBuf: PChar; OldLen: Integer; const Oldfmt: TWAVEFORMATEX;
             var NewBuf: PChar; const Newfmt: TWAVEFORMATEX): LongInt;
var
  i, j, k: Integer;
  Scale: Single;
  SamplePos: Single;
  LeftPos, RightPos: Integer;
  SrcSmall, SrcSmall2: SmallInt;
  SrcByte, SrcByte2: Byte;
begin
  Scale := Newfmt.nSamplesPerSec / Oldfmt.nSamplesPerSec;       //采样比例
  i := OldLen div Oldfmt.nBlockAlign;           //音频格式块对齐方式
  j := Trunc(Newfmt.nSamplesPerSec / Oldfmt.nSamplesPerSec * i);//转换比例
  Result := Newfmt.nBlockAlign * j;     //新的长度
//  GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, Result);
  ReallocMem(NewBuf, Result);   //分配内存

  SrcByte := 9;
  SrcSmall := 0;
  SrcByte2 := 0;
  SrcSmall2 := 0;
  for k := 0 to j - 1 do        //数据转换
  begin
    SamplePos := k / Scale;     //新的数据地址
    LeftPos := Trunc(SamplePos);
    RightPos := LeftPos + 1;    //下一个数据
    if RightPos > i - 1 then
       RightPos := LeftPos;

    if Oldfmt.wBitsPerSample = 16 then
    begin       //采样大小为 16 位
       Srcsmall := Round(PCMInt(OldBuf + LeftPos * Oldfmt.nBlockAlign)^ * (1 -
            SamplePos + LeftPos) + PCMInt(OldBuf + RightPos * Oldfmt.nBlockAlign)^ *
            (SamplePos - LeftPos));     //取高位数据值  (左声道)
       if Oldfmt.nChannels > 1 then     //双声道
          SrcSmall2 := Round(PCMInt(OldBuf + LeftPos * Oldfmt.nBlockAlign + 2)^ *
            (1 - SamplePos + LeftPos) + PCMInt(OldBuf + RightPos * Oldfmt.nBlockAlign
            + 2)^ * (SamplePos - LeftPos))      //取低位数据值  (右声道)
       else     //单声道
          SrcSmall2 := SrcSmall;        
    end
    else        //8 位
    begin       //取高位数据值  (左声道)
      SrcByte := Round(Byte((OldBuf + LeftPos * Oldfmt.nBlockAlign)^) * (1 - SamplePos + LeftPos)
           + Byte((OldBuf + RightPos * Oldfmt.nBlockAlign)^) * (SamplePos - LeftPos));
      if Oldfmt.nChannels > 1 then      //双声道
         SrcByte2 := Round(Byte((OldBuf + LeftPos * Oldfmt.nBlockAlign + 1)^) * (1 - SamplePos + LeftPos)
           + Byte((OldBuf + RightPos * Oldfmt.nBlockAlign+1)^) * (SamplePos - LeftPos))
      else      //单声道
         SrcByte2 := SrcByte;
    end;
    //
    //  开始数转换
    //
    if Newfmt.wBitsPerSample = 16 then          //新的采样大小为 16 位
      if Oldfmt.wBitsPerSample = 8 then         //旧的采样大小为 8 位
        if Newfmt.nChannels = 1  then           //单声道
           PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := Bits8To16((SrcByte + SrcByte2) div 2)
        else                                    //双声道
           PCMlong(NewBuf + k * Newfmt.nBlockAlign)^ := Bits8To16(SrcByte) + (Bits8To16(SrcByte2) shl 16)
      else                                      //旧的采样大小为 16 位
          if Newfmt.nChannels = 1  then         //单声道
             PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := (SrcSmall + SrcSmall2) div 2
          else                                  //双声道
             PCMlong(NewBuf + k * Newfmt.nBlockAlign)^ := SrcSmall+(SrcSmall2 shl 16)
    else                                        //新的采样大小为 8 位
      if Oldfmt.wBitsPerSample = 8 then         //旧的采样大小为 8 位
        if Newfmt.nChannels = 1  then           //单声道
           (NewBuf + k * Newfmt.nBlockAlign)^ := CHR((SrcByte + SrcByte2) div 2)
        else                                    //双声道
           PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := SrcByte + (SrcByte2 shl 8)
      else                                      //旧的采样大小为 16 位
         if Newfmt.nChannels = 1  then          //单声道
            (NewBuf + k * Newfmt.nBlockAlign)^ := CHR(Bits16To8((SrcSmall + SrcSmall2) div 2))
        else                                    //双声道
            PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := Bits16To8(SrcSmall) + (Bits16To8(SrcSmall2) shl 8);
  end;
end;

end.

⌨️ 快捷键说明

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