📄 mmacmdlg.pas
字号:
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 + -