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

📄 mmacmdlg.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
                  begin
                     afc.fdwEnum := ACM_FORMATENUMF_SUGGEST;
                     afc.pwfxEnum:= pwfxSrc;
                  end;
       efRestrict:if (pwfxSrc <> nil) then
                  begin
                     afc.fdwEnum := ACM_FORMATENUMF_WFORMATTAG;
                     afc.pwfxEnum:= pwfxSrc;
                  end;
        else afc.fdwEnum  := 0;
   end;

   afc.hInstance       := 0;
   afc.pszTemplateName := nil;
   afc.lCustData       := 0;
   afc.pfnHook         := nil;

   TryCount := 0;

Again:

   mmr := acmFormatChoose(@afc);
   if (mmr <> 0) then
   begin
      if (mmr <> ACMERR_CANCELED) then
      begin
         inc(TryCount);
         if (TryCount = 1) then goto Again; // Bug Fix for Win98
         raise EMMACMError.Create('acmFormatChoose failed with error '+IntToStr(mmr));
      end;
      exit;
   end;
   Result := True;
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.ChooseFilter(pwfltrSrc: PWaveFilter; Title: String): Boolean;
var
   afc    : TACMFilterChoose;
   aBuf   : array[0..255] of char;
   mmr    : MMRESULT;
   cbwfltr: Longint;

begin
   Result := False;

   if not ACMPresent or (FNumFilters <= 0) then exit;

   { initialize the TACMFILTERCHOOSE members }
   FillChar(afc, sizeOf(afc), 0);

   cbwfltr := Max(FMaxFilterSize, sizeof(TWaveFilter));

   if (pwfltrSrc <> nil) then
   begin
      if (cbwfltr > FMaxFilterSize) then
      begin
         FMaxFilterSize := cbwfltr;
         FreeWaveFilter(FPWaveFilter);
         AllocWaveFilter(FPWaveFilter);
      end;

      move(pwfltrSrc^, FPWaveFilter, pwfltrSrc^.cbStruct);
      afc.fdwStyle := ACMFILTERCHOOSE_STYLEF_INITTOFILTERSTRUCT;
   end;

   afc.cbStruct        := sizeOf(afc);
   if (Owner <> nil) then
       afc.hwndOwner   := (Owner as TWinControl).Handle;
   afc.pwfltr          := FPWaveFilter;
   afc.cbwfltr         := cbwfltr;
   if (Title <> '') then
       afc.pszTitle    := StrPCopy(aBuf, Title);

   afc.szFilterTag[0]  := #0;
   afc.szFilter[0]     := #0;
   afc.pszName         := nil;
   afc.cchName         := 0;
   afc.fdwEnum         := 0;

   mmr := acmFilterChoose(@afc);
   if (mmr <> 0) then
   begin
      if (mmr <> ACMERR_CANCELED) then
         raise EMMACMError.Create('acmFilterChoose failed with error '+IntToStr(mmr));

      exit;
   end;
   Result := True;
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.QueryConvert(pwfxDst: PWaveFormatEx; pwfltr: PWaveFilter): Boolean;
var
   mmr: MMRESULT;

begin
   Result := False;

   if ACMPresent and (FSource<>nil) and (Wave<>nil) then
   begin
      mmr := acmStreamOpen(nil, 0, Wave.PWaveFormat, pwfxDst, pwfltr, 0, 0,
                           ACM_STREAMOPENF_NONREALTIME or
                           ACM_STREAMOPENF_QUERY);

      if (mmr = 0) then Result := True;
   end;
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.ProcessFile(const FileName: TFileName; pwfxDst: PWaveFormatEx;
                            pwfltr: PWaveFilter): Boolean;
Label ERROR_CONVERT;
var
   mmr: MMRESULT;
   Cancel: Boolean;
   FOnProgress: TMMWaveProgress;
   TmpFile, DestFile: PChar;
   CurByte, NumBytes, NumRead, dw: Longint;
   lpwioSrc, lpwioDst: PWaveIOCB;
   pSrc,pDst: PChar;
   SrcBufSize,DstBufSize: Longint;
   pwfxSrc: PWaveFormatEx;
   has: THACMSTREAM;
   ash : TACMStreamHeader;

begin
   Result := False;
   if not ACMPresent or (FSource = nil) or
      (Wave = nil) or Wave.Empty or (FileName = '') then exit;

   Cancel := False;
   pSrc := nil;
   pDst := nil;
   lpwioSrc := Wave.PWaveIOInfo;
   lpwioDst:= nil;
   pwfxSrc := Wave.PWaveFormat;
   if (pwfxDst = nil) then pwfxDst := pwfxSrc;

   if not QueryConvert(pwfxDst, pwfltr) then
      raise EMMACMError.Create(LoadResStr(IDS_ACMBADFORMAT));

   { open the source file and set position to data chunk }
   if wioWaveOpen(lpwioSrc) <> 0 then
      goto ERROR_CONVERT;

   { set the bytes to convert }
   NumBytes := lpwioSrc^.dwBytesLeft;

   { create the dest. WAVEIOINFO }
   if wioCreateFileInfo(lpwioDst, pwfxDst) <> 0 then
      goto ERROR_CONVERT;

   { copy all known chunks to the destination }
   if wioCopyFileInfo(lpwioDst, lpwioSrc) <> 0 then
      goto ERROR_CONVERT;

   TmpFile := StrAlloc(MAX_PATH+1);
   DestFile := StrAlloc(MAX_PATH+1);

   { first create a temporary file for the destination file }
   StrPCopy(TmpFile, FileName);
   if Not wioFileCreateTemp(TmpFile) then
      goto ERROR_CONVERT;

   { write the new Header to disc }
   if wioWriteFileInfo(lpwioDst, TmpFile) <> 0 then
      goto ERROR_CONVERT;

   { compute source bytes to read (round down to nearest }
   { block for one second of data)                       }
   with pwfxSrc^ do
   SrcBufSize := nAvgBytesPerSec-(nAvgBytesPerSec mod nBlockAlign);

   mmr := acmStreamOpen(@has, 0, pwfxSrc, pwfxDst, pwfltr, 0, 0,
                        ACM_STREAMOPENF_NONREALTIME);
   if (mmr <> 0) then
   begin
      ShowMessage('acmStreamOpen failed with error '+IntToStr(mmr));
      goto ERROR_CONVERT;
   end;

   mmr := acmStreamSize(has, SrcBufSize, DstBufSize,
                        ACM_STREAMSIZEF_SOURCE);
   if (mmr <> 0) then
   begin
      ShowMessage('acmStreamSize failed with error '+IntToStr(mmr));
      goto ERROR_CONVERT;
   end;

   { allocate the src and dst buffers for reading/converting data }
   pSrc := GlobalAllocPtr(GHND, SrcBufSize);
   if (pSrc = Nil) then goto ERROR_CONVERT;
   pDst := GlobalAllocPtr(GHND, DstBufSize);
   if (pDst = Nil) then goto ERROR_CONVERT;

   { setup the stream header structure }
   ash.cbStruct          := sizeof(ash);
   ash.fdwStatus         := 0;
   ash.dwUser            := 0;
   ash.pbSrc             := pSrc;
   ash.cbSrcLength       := SrcBufSize;
   ash.cbSrcLengthUsed   := 0;
   ash.dwSrcUser         := SrcBufSize;
   ash.pbDst             := pDst;
   ash.cbDstLength       := DstBufSize;
   ash.cbDstLengthUsed   := 0;
   ash.dwDstUser         := DstBufSize;

   mmr := acmStreamPrepareHeader(has, @ash, 0);
   if (mmr <> 0) then
   begin
      ShowMessage('acmStreamPrepareHeader failed with error '+IntToStr(mmr));
      goto ERROR_CONVERT;
   end;

   FOnProgress := Wave.OnProgress;

   CurByte := 0;
   while CurByte < NumBytes do
   begin
      { read the data to convert }
      NumRead := min(SrcBufSize, NumBytes - CurByte);
      NumRead := wioWaveReadData(lpwioSrc, pSrc, NumRead);
      if (NumRead <= 0) then break;

      ash.cbSrcLength     := NumRead;
      ash.cbDstLengthUsed := 0;

      mmr := acmStreamConvert(has, @ash, ACM_STREAMCONVERTF_BLOCKALIGN);
      if (mmr <> 0) then
      begin
         ShowMessage('acmStreamConvert failed with error '+IntToStr(mmr));
         goto ERROR_CONVERT;
      end;

      { wait until the converting is done }
      while (ash.fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;

      { adjust the current read position }
      NumRead := NumRead - ash.cbSrcLengthUsed;
      if (NumRead <> 0) then
      begin
         mmioSeek(lpwioSrc^.hmmio, -NumRead, SEEK_CUR);
         inc(lpwioSrc^.dwBytesLeft, NumRead);
      end;

      inc(CurByte, ash.cbSrcLengthUsed);

      NumRead := ash.cbDstLengthUsed;
      if (NumRead <= 0) then break;

      { have we space on the drive ? }
      if not GetDiskFree(ExtractFilePath(TmpFile),NumRead+10240) then
         goto ERROR_CONVERT;

      { write the data out as we go... }
      if wioWaveWriteData(lpwioDst, pDst, NumRead) <> NumRead then
         goto ERROR_CONVERT;

      { let the user have some time }
      Application.ProcessMessages;
      if assigned(FOnProgress) then
         FOnProgress(Self, CurByte, NumBytes, Cancel);
      if Cancel then goto ERROR_CONVERT;
   end;

   { cleanup pass }
   while True do
   begin
      dw := 0;
      NumRead := min(SrcBufSize, NumBytes - CurByte);
      if (NumRead > 0) then
      begin
         dw := wioWaveReadData(lpwioSrc, pSrc, NumRead);
         if (dw <= 0) then break;
      end;

      ash.cbSrcLength     := dw;
      ash.cbDstLengthUsed := 0;

      mmr := acmStreamConvert(has, @ash, ACM_STREAMCONVERTF_BLOCKALIGN or
                                         ACM_STREAMCONVERTF_END);
      if (mmr <> 0) then
      begin
         ShowMessage('acmStreamConvert failed with error '+IntToStr(mmr));
         goto ERROR_CONVERT;
      end;

      { wait until the converting is done }
      while (ash.fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;

      dw := ash.cbDstLengthUsed;
      if (dw = 0) then
      begin
         ash.cbDstLengthUsed := 0;

         mmr := acmStreamConvert(has, @ash, ACM_STREAMCONVERTF_END);
         if (mmr = 0) then
         begin
            { wait until the converting is done }
            while (ash.fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;
         end;

         dw := ash.cbDstLengthUsed;
         if (dw = 0) then break;
      end;

      { have we space on the drive ? }
      if not GetDiskFree(ExtractFilePath(TmpFile),dw+10240) then
         goto ERROR_CONVERT;

      { write the data out as we go... }
      if wioWaveWriteData(lpwioDst, pDst, dw) <> dw then
         goto ERROR_CONVERT;

      { adjust the current read position }
      dw := NumRead - ash.cbSrcLengthUsed;
      if (dw <> 0) then
      begin
         mmioSeek(lpwioSrc^.hmmio, -dw, SEEK_CUR);
         inc(lpwioSrc^.dwBytesLeft, dw);
      end;

      inc(CurByte, ash.cbSrcLengthUsed);

      if (ash.cbDstLengthUsed = 0) then break;

      { let the user have some time }
      Application.ProcessMessages;
      if assigned(FOnProgress) then
         FOnProgress(Self, CurByte, NumBytes, Cancel);
      if Cancel then goto ERROR_CONVERT;
   end;

   { close source and temp file }
   wioWaveClose(lpwioSrc);
   wioWaveClose(lpwioDst);

   StrPCopy(DestFile, FileName);

   { delete the real destination file (if exits) }
   if wioFileExists(DestFile) then wioFileDelete(DestFile);

   { rename the temp file to the destination file }
   if mmioRename(TmpFile, DestFile, Nil, 0) <> 0 then
      goto ERROR_CONVERT;

   Result := True;

ERROR_CONVERT:

   wioWaveClose(lpwioSrc);
   wioWaveClose(lpwioDst);
   wioFreeFileInfo(lpwioDst);
   { clear up the stream stuff }
   if (ash.fdwStatus and ACMSTREAMHEADER_STATUSF_PREPARED <> 0) then
   begin
      ash.cbSrcLength := SrcBufSize;
      ash.cbDstLength := DstBufSize;
      mmr := acmStreamUnprepareHeader(has, @ash, 0);
      if (mmr <> 0) then
         ShowMessage('acmStreamUnprepareHeader failed with error '+IntToStr(mmr));
   end;
   acmStreamClose(has, 0);

   if (pSrc <> nil) then GlobalFreePtr(pSrc);
   if (pDst <> nil) then GlobalFreePtr(pDst);

   { make sure we delete the temp file }
   if wioFileExists(TmpFile) then wioFileDelete(TmpFile);
   StrDispose(TmpFile);
   StrDispose(DestFile);
   if not Result then
      if not Cancel then
         raise EMMACMError.Create(LoadResStr(IDS_ACMERROR))
      else
         raise EMMACMError.Create(LoadResStr(IDS_ACMABORT));
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.CreateFile(const FileName: TFileName): Boolean;
begin
   Result := False;
   if ACMPresent and (FSource <> nil) and (Wave <> nil) then
   begin
      if not Wave.Empty and (FileName <> '') and (FPWaveFormatEx <> nil) then
      begin
         Wave.CreateFile(FileName, FPWaveFormatEx);

         Result := True;
      end;
   end;
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.ConvertFile(const FileName: TFileName): Boolean;
begin
   Result := False;
   if ACMPresent and (FNumConverters > 0) and (FSource <> nil) and
      (Wave <> nil) and not Wave.Empty and (FileName <> '') then
   begin
      Result := ProcessFile(FileName, FPWaveFormatEx, nil);
   end;
end;

{-- TMMACM -------------------------------------------------------------}
function TMMACM.FilterFile(const FileName: TFileName): Boolean;
begin
   Result := False;
   if ACMPresent and (FNumFilters > 0) and (FSource <> nil) and
      (Wave <> nil) and not Wave.Empty and (FileName <> '') then
   begin
      Result := ProcessFile(FileName, nil, FPWaveFilter);
   end;
end;

end.

⌨️ 快捷键说明

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