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

📄 tcmwavetype.pas

📁 语音与识别技术包含很多C语言处理模块系统
💻 PAS
📖 第 1 页 / 共 3 页
字号:
//***********************************************************************//
//                                                                       //
//   音频处理公用单元                                                    //
//   单元名: TCMWaveType                                                 //
//   功能: 提供放音与录音的公共数据和函数                                //
//   日期: 2003 年 1月 13日                                              //
//                                                                       //
//***********************************************************************//

unit TCMWaveType;

interface

uses
  Windows, SysUtils, Messages, Classes, Graphics, MMSystem, Forms, Dialogs;

//***********************************************************************//
//                                                                       //
//   当前的播放状态                                                      //
//                                                                       //
//***********************************************************************//
Type
  TCMPlaying = (CPNONE,                 //没有在任何状态下
                CPPLAYING,              //正处于播放状态中
                CPSTOPING,              //正处于停止状态中
                CPPAUSEING              //正处于暂停状态中
                );

//***********************************************************************//
//                                                                       //
//   当前的录音状态                                                      //
//                                                                       //
//***********************************************************************//
Type                      
  TCMRecording = (CRNONE,               //没有在任何状态下
                  CRRECORDING,          //正处于录音状态中
                  CRSTOPING,            //正处于停止状态中
                  CRPAUSEING            //正处于暂停状态中
                  );

//***********************************************************************//
//                                                                       //
//   文件是以何种方式打开                                                //
//                                                                       //
//***********************************************************************//
Type
  TSave_Type = (CS_SAVE_PLAY,           //以播放方式
                CS_SAVE_RECORD,         //以录音方式
                CS_SAVE_NEW             //以新建方式
                );

//***********************************************************************//
//                                                                       //
//   播放模式                                                            //
//                                                                       //
//***********************************************************************//
Type
  TPlay_Type = (PLAY_ALL,               //播放全部
                PLAY_AREA               //区域播放
                );

//***********************************************************************//
//                                                                       //
//   音频数据编辑方式                                                    //
//                                                                       //
//***********************************************************************//
Type
  TWaveEdit_Type = (CM_WE_COPY,         //复制音频数据
                    CM_WE_CUT,          //剪切音频数据
                    CM_WE_DEL,          //删除音频数据
                    CM_WE_PASTE         //粘贴音频数据
                    );

//***********************************************************************//
//                                                                       //
//   音频时间格式                                                        //
//                                                                       //
//***********************************************************************//
Type
  TCM_Wave_Time = Record
    Hour: DWORD;                        //小时
    Minute: DWORD;                      //分钟
    Second: DWORD;                      //秒
    Heroism: DWORD;                     //豪秒
  end;

//***********************************************************************//
//                                                                       //
//   波形显示数据记录                                                    //
//                                                                       //
//***********************************************************************//
Type
  TDrawWave_Type = Record
    FileType: TSave_Type;               //文件打开的方式
    hio: HMMIO;                         //音频文件名柄( 以播放方式打开时有效 )
    Flag: Integer;                      //波形显示周期
    FileName: String;                   //文件名( 以录音方式打开时有效 )
    Length: LongInt;                    //音频数据的长度
    DesCanvas: TCanvas;                 //要显示波形的目标画布
    DH: SmallInt;                       //目标画布的工作区域的高度
    DW: SmallInt;                       //目标画布的工作区域的宽度
    DesBitMap: TBitMap;                 //画波形时用的非可视源位图对像
  end;

//***********************************************************************//
//                                                                       //
//   音频类回调过程处理状态                                              //
//                                                                       //
//***********************************************************************//
Type
  TWaveLoopEventType = (WA_EN_NONE,     //没有任何状态
                        WA_EN_OPENFILE  //打开文件状态
                        );

//***********************************************************************//
//                                                                       //
//   音频类回调过程处理过程                                              //
//                                                                       //
//***********************************************************************//
Type
  TWaveLoopNotifyEvent = procedure(WaveEvent: TWaveLoopEventType; Max, Min,
                                   Position: DWORD) of object;

Type
  PCMInt = ^SmallInt;             //短整型指针
  PCMlong = ^LongInt;             //长整型指针
  EMMIO = class(Exception);       //多媒体异常类

Const
  LoadMemSize   = 1024 * 5000;//0;//15000;   //数据播放的长度( 要开辟的内存大小 必须是 32 的倍数)

  CM_PLAYBEGIN  = WM_user + $A1;  //开始播放
  CM_PLAYEND    = WM_user + $A2;  //播放完毕

  CM_PLAYPAUSE  = WM_user + $A3;  //暂停播放
  CM_PLAYREST   = WM_user + $A4;  //恢复播放

  CM_BEGINSAVE  = WM_user + $A5;  //开始保存消息
  CM_SAVEPOSI   = WM_user + $A6;  //当前保存位置消息( wParam : 当前位置 )
  CM_ENDSAVE    = WM_user + $A7;  //保存完消息

  CM_BEGINDRAW  = WM_user + $A8;  //开始画波形消息
  CM_DRAWPOSI   = WM_user + $A9;  //当前画到的位置消息( wParam : 当前位置 )
  CM_ENDDRAW    = WM_user + $AA;  //波形画完消息

  CM_BEGINCOPY  = WM_user + $AB;  //开始复制数据

  CM_BEGINCUT   = WM_user + $AC;  //开始剪切数据

  CM_BEGINPASTE = WM_user + $AD;  //开始粘贴数据

  CM_BEGINDEL   = WM_user + $AE;  //开始删除数据

  CM_BEGINUNDO  = WM_user + $AF;  //开始撤消数据

  CM_EDIEND     = WM_user + $B0;  //数据编辑完毕
  CM_EDITPOI    = WM_user + $B1;  //数据编辑进度( wParam : 当前位置. 当 wParam 为 0 时, lParam : 在以前进度的基础上加的长度 )
  CM_EDITLENGTH = WM_user + $B2;  //数据处理的长度( wParam : 数据长度 )

procedure Wave_SaveFile(const FileName, TempFileName: String; DataLength: LongInt;
          WaveFmt: TWAVEFORMATEX; Dhio: HMMIO; tSave: TSave_Type;
          const StartPoi: LongInt = 0; const SaveLength: LongInt = 0);

function Wave_Save_ConvertFile(const NewFileName: String; DataLength: LongInt;
          NewWaveFmt, OldWaveFmt: TWAVEFORMATEX; Dhio: HMMIO; ShowPoi: TWaveLoopNotifyEvent): LongInt;

procedure DrawPartWave(const Flag: Integer; Buf: PChar; Length: LongInt;
          DesCanvas: TCanvas; DH, DW: SmallInt; DesBitMap: TBitMap;
          DrawLineColor, DrawBackColor: TColor; Draw: Boolean = True);

procedure HawDrawWave(Buf: PChar; Length: LongInt; DesCanvas: TCanvas;
          DH, DW: SmallInt; Min, Max: LongInt; DrawLineColor, DrawBackColor: TColor;
          StartPoi: LongInt = 0; DrawLength: LongInt = 0);

procedure DrawAllWave(Dw_Type: TDrawWave_Type; var WaveMin, WaveMax: LongInt;
          DrawLineColor, DrawBackColor: TColor; Draw: Boolean = True);
                         
function ConvertWave(OldBuf: PChar; OldLen: Integer; const OldFmt: TWAVEFORMATEX;
         var NewBuf: PChar; const Newfmt: TWAVEFORMATEX): LongInt;

implementation
                         
//***********************************************************************//
//                                                                       //
//   16 位数据转换成 8 位数                                              //
//                                                                       //
//***********************************************************************//
function Bits16To8(Src: WORD): Byte;
begin
  Result := Byte((Src shr 8) xor $80);
end;

//***********************************************************************//
//                                                                       //
//   8 位数据转换成 16 位数                                              //
//                                                                       //
//***********************************************************************//
function Bits8To16(Src: Byte): WORD;
begin
  Result := WORD((Src xor $80) shl 8 );
end;

//***********************************************************************//
//                                                                       //
//   本单元公用变量声明                                                  //
//                                                                       //
//***********************************************************************//
var
  DrawMin: Integer;     //波形的最小值
  DrawMax: Integer;     //波形的最大值

//***********************************************************************//
//                                                                       //
//   保存音频文件                                                        //
//   参数:                                                               //
//       FileName       : 要保存的文件名                                 //
//       TempFileName   : 源文件名 ( 在录音状态下保存文件有效 )          //
//       DataLength     : 音频数据的长度                                 //
//       WaveFmt        : 波形格式                                       //
//       Dhio           : 源音频文件名柄 ( 在放音状态下保存文件有效 )    //
//       tSave          : 在何种状态下保存文件                           //
//       StartPoi       : 要保存的音频数据的起始位置                     //
//       SaveLength     : 要保存的音频数据的长度( 如果为 0 则全部保存 )  //
//   说明:                                                               //
//       StartPoi , SaveLength 只在放音状态下保存时有效                  //
//   返回值: 无                                                          //
//                                                                       //
//***********************************************************************//
procedure Wave_SaveFile(const FileName, TempFileName: String; DataLength: LongInt;
          WaveFmt: TWAVEFORMATEX; Dhio: HMMIO; tSave: TSave_Type;
          const StartPoi: LongInt = 0; const SaveLength: LongInt = 0);
var
  hio: HMMIO;           //音频文件句柄
  Buf: PChar;           //用于读取数据的缓冲区
  ck: TMMCKINFO;        //音频信息结构
  SaveLoop: LongInt;    //循环读取数据的次数
  Length: LongInt;      //要保存数据的长度
  i: LongInt;
  MODSaveSize: LongInt; //最后一次数据的长度
  SaveSize: LongInt;    //要写入文件的数据的长度
  TempFile:Integer;     //临时文件句柄 ( 在录音状态下时有效 )
  SaveStartPoi: LongInt;//保存数据在文件中的开始处
begin
  Application.ProcessMessages;  //处理 Windows 消息

  TempFile := 0;

  if (tSave = CS_SAVE_PLAY) AND (SaveLength > 0) AND (StartPoi < DataLength)
     AND (StartPoi > 0) AND ((StartPoi + SaveLength) <= DataLength) AND (StartPoi < DataLength) then
  begin
     Length := SaveLength;
     SaveStartPoi := StartPoi;
  end
  else begin
     Length := DataLength;
     SaveStartPoi := 0;
  end;
  SaveLoop := Length DIV LoadMemSize;
  MODSaveSize := 0;
  if (Length MOD LoadMemSize) <> 0 then
  begin
     SaveLoop := SaveLoop + 1;
     MODSaveSize := Length MOD LoadMemSize;
  end;

  if tSave <> CS_SAVE_NEW then
     SendMessage(Application.MainForm.Handle, CM_BEGINSAVE, SaveLoop, 0);

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

  //创建成一个新的音频文件
  hio := mmioOpen(PChar(FileName), NIL, MMIO_CREATE + MMIO_READWRITE);
  if hio = 0 then
    raise EMMIO.Create('无法创建文件');
  Try
    if WaveFmt.wFormatTag = WAVE_FORMAT_PCM then        //波形格式的大小
      ck.cksize := Length + 4 + 8 + SizeOf(WaveFmt) - 2 + 8
    else
      ck.cksize := Length + 4 + 8 + SizeOf(WaveFmt) + WaveFmt.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 WaveFmt.wFormatTag = WAVE_FORMAT_PCM then
      ck.cksize := SizeOf(WaveFmt) - 2                  //fmt 块的大小
    else
      ck.cksize := SizeOf(WaveFmt) + WaveFmt.cbSize;

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

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

    if tSave = CS_SAVE_NEW then
    begin
      mmioClose(hio, 0);          //关闭目标音频文件
      Exit;
    end;

    case tSave of       //把文件指针移到指定位置
      CS_SAVE_PLAY: mmioSeek(Dhio, DataLength - SaveStartPoi, SEEK_END);
      CS_SAVE_RECORD:
      begin
         TempFile := FileOpen(TempFileName, fmOpenRead);        //以只读方式打开文件                
         if TempFile = 0 then
            raise EMMIO.Create('数据读取错误');
      end;
    end;

    for i := 1 to SaveLoop do
    begin
       if (MODSaveSize <> 0) AND (i = SaveLoop) then
       begin

⌨️ 快捷键说明

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