📄 mmacmsup.pas
字号:
{------------------------------------------------------------------------}
function acmInitConvert(lpACMConvert: PACMConvert; pwfxSrc,pwfxDst: PWaveFormatEx; RealTime: Boolean): Boolean;
Label Ready;
var
Buf: array[0..1024] of Char;
pwfx: PWaveFormatEx;
dwSuggest,dwFlags: Longint;
bFreeSrc: Boolean;
function SetupConvert(pwfxSrc, pwfxDst: PWaveFormatEx; UseMpeg: Boolean): Boolean;
var
Stream: PACMStream;
dwOpenFlags: Longint;
begin
Result := False;
if not UseMpeg then
begin
Stream := GlobalAllocMem(sizeOf(TACMStream));
with Stream^ do
try
dwOpenFlags := 0;
if not RealTime then dwOpenFlags := ACM_STREAMOPENF_NONREALTIME;
if acmStreamOpen(@acmStream, 0, pwfxSrc, pwfxDst, nil, 0, 0, dwOpenFlags) <> 0 then
exit;
if (lpACMConvert^.lpDstBuffer <> nil) then
begin
dwSrcBufferSize:= lpACMConvert^.dwDstBufferSize;
lpSrcBuffer := lpACMConvert^.lpDstBuffer;
bFreeSrc := False;
end
else
begin
if (lpACMConvert^.lpSrcBuffer = nil) then
begin
dwSrcBufferSize:= 4*lpACMConvert^.dwSrcBufferSize;
lpSrcBuffer := GlobalAllocMem(dwSrcBufferSize);
bFreeSrc := True;
lpACMConvert^.bFreeSrcBuffer := True;
end
else
begin
dwSrcBufferSize:= lpACMConvert^.dwSrcBufferSize;
lpSrcBuffer := lpACMConvert^.lpSrcBuffer;
bFreeSrc := False;
end;
end;
if acmStreamSize(acmStream, dwSrcBufferSize, dwDstBufferSize, ACM_STREAMSIZEF_SOURCE) <> 0 then
exit;
lpDstBuffer := GlobalAllocMem(dwDstBufferSize);
{ setup the first stream header structure }
with acmStreamHeader do
begin
cbStruct := sizeof(TACMStreamHeader);
fdwStatus := 0;
dwUser := 0;
pbSrc := lpSrcBuffer;
cbSrcLength := dwSrcBufferSize;
cbSrcLengthUsed := 0;
dwSrcUser := dwSrcBufferSize;
pbDst := lpDstBuffer;
cbDstLength := dwDstBufferSize;
cbDstLengthUsed := 0;
dwDstUser := dwDstBufferSize;
end;
dwRemaining := 0;
if acmStreamPrepareHeader(acmStream, @acmStreamHeader, 0) <> 0 then
exit;
lpACMConvert^.lpDstBuffer := lpDstBuffer;
lpACMConvert^.dwDstBufferSize := dwDstBufferSize;
lpACMConvert^.Streams.Add(Stream);
Result := True;
finally
if not Result then
begin
acmStreamUnprepareHeader(acmStream, @acmStreamHeader, 0);
acmStreamClose(acmStream, 0);
if bFreeSrc then GlobalFreeMem(Pointer(lpSrcBuffer));
GlobalFreeMem(Pointer(lpDstBuffer));
GlobalFreeMem(Pointer(Stream));
end;
end;
end
{$IFDEF USEWAVEMPEG}
else
with lpACMConvert^ do
begin
try
if (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3) then
begin
bUseL3Decoder := True;
pL3DLL := mp3DecInit;
if (pL3DLL = 0) then exit;
dwDstBufferSize := 2*((dwSrcBufferSize*pwfxDst^.nAvgBytesPerSec) div pwfxSrc^.nAvgBytesPerSec);
lpDstBuffer := GlobalAllocMem(dwDstBufferSize);
if mp3DecOpenEx(pL3DLL,@lpDecBuffer,sizeOf(lpDecBuffer),0,0,0,False) <> 0 then
begin
Result := False;
exit;
end;
{ create critical section object }
FillChar(DataSection, SizeOf(DataSection), 0);
InitializeCriticalSection(DataSection);
end
else
begin
bUseL2Decoder := True;
pL2DLL := CreateL2DLLInstance;
if (pL2DLL = nil) then exit;
dwDstBufferSize := ((dwSrcBufferSize*pwfxDst^.nAvgBytesPerSec) div pwfxSrc^.nAvgBytesPerSec)+4096;
lpDstBuffer := GlobalAllocMem(dwDstBufferSize);
if (pL2DLL.mpegOpen('external://', 0, 0,0, 0) <> 0) then
begin
Result := False;
exit;
end;
pL2DLL.mpegCommand(0, MP3_KEY, 0, 0, MP3_KEY_STR);
{ create critical section object }
FillChar(DataSection, SizeOf(DataSection), 0);
InitializeCriticalSection(DataSection);
end;
Result := True;
finally
if not Result then
begin
if (pL3DLL <> 0) then
begin
mp3DecClose(pL3DLL);
mp3DecDone(pL3DLL);
pL3DLL := 0;
GlobalFreeMem(Pointer(lpDstBuffer));
end;
if (pl2DLL <> nil) then
begin
pL2DLL.mpegClose;
FreeL2DLLInstance(pL2DLL);
pL2DLL := nil;
GlobalFreeMem(Pointer(lpDstBuffer));
end;
end;
end;
end
{$ENDIF};
end;
begin
Result := False;
if acmDLLLoaded and (HiWord(acmGetVersion) >= $0200) and
(pwfxSrc <> nil) and (pwfxSrc <> nil) then
begin
if acmMustConvert(pwfxSrc,pwfxDst) then
begin
dwFlags := ACM_STREAMOPENF_QUERY;
if not RealTime then dwFlags := dwFlags or ACM_STREAMOPENF_NONREALTIME;
{$IFDEF USEWAVEMPEG}
if ((pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
(pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3)) and
(pwfxDst.wFormatTag = WAVE_FORMAT_PCM) then
begin
if (pwfxSrc^.nSamplesPerSec = pwfxDst.nSamplesPerSec) and
(pwfxSrc^.nChannels = pwfxDst.nChannels) then
begin
Result := SetupConvert(pwfxSrc,pwfxDst,True);
exit;
end;
end
{$ENDIF};
if (acmStreamOpen(nil, 0, pwfxSrc, pwfxDst, nil, 0, 0, dwFlags) = 0) then
begin
Result := SetupConvert(pwfxSrc,pwfxDst,False);
exit;
end;
pwfx := Pointer(@Buf);
FillChar(pwfx^, sizeOf(pwfx^), 0);
if (pwfxSrc^.wFormatTag <> WAVE_FORMAT_PCM) then
begin
pwfx^.wFormatTag := WAVE_FORMAT_PCM;
pwfx^.nChannels := pwfxDst^.nChannels;
pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
dwSuggest := ACM_FORMATSUGGESTF_WFORMATTAG or
ACM_FORMATSUGGESTF_NCHANNELS or
ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
{ 'suggest' a format' }
if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
goto ready;
dwSuggest := ACM_FORMATSUGGESTF_WFORMATTAG;
{ 'suggest' a format' }
if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
goto ready;
end
else if (pwfxSrc^.nChannels <> pwfxDst^.nChannels) or
(pwfxSrc^.nSamplesPerSec <> pwfxDst^.nSamplesPerSec) then
begin
pwfx^.nChannels := pwfxDst^.nChannels;
pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
dwSuggest := ACM_FORMATSUGGESTF_NCHANNELS or
ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
{ 'suggest' a format' }
if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
begin
if (acmStreamOpen(nil, 0, pwfx, pwfxDst, nil, 0, 0, dwFlags) = 0) then
goto ready;
if (pwfx^.wBitsperSample = 16) then
pwfx^.wBitsPerSample := 8
else
pwfx^.wBitsPerSample := 16;
dwSuggest := dwSuggest or ACM_FORMATSUGGESTF_WBITSPERSAMPLE;
if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
goto ready;
end;
end;
exit;
Ready:
if (acmStreamOpen(nil, 0, pwfxSrc, pwfx, nil, 0, 0, dwFlags) <> 0) then
exit;
Result := SetupConvert(pwfxSrc,pwfx,False);
if Result and acmMustConvert(pwfx,pwfxDst) then
Result := acmInitConvert(lpACMConvert,pwfx,pwfxDst,RealTime);
end;
end;
end;
{-------------------------------------------------------------------------}
function acmBeginConvert(pwfxSrc,pwfxDst: PWaveFormatEx;
SrcBuffer: PChar; SrcBufSize: Longint;
RealTime: Boolean): PACMConvert;
begin
if acmDLLLoaded and (HiWord(acmGetVersion) >= $0200) and
(pwfxSrc <> nil) and (pwfxDst <> nil) then
begin
Result := GlobalAllocMem(sizeOf(TACMConvert));
with Result^ do
begin
Streams := TList.Create;
lpSrcBuffer := SrcBuffer;
dwSrcBufferSize := (SrcBufSize div pwfxSrc^.nBlockAlign)*pwfxSrc^.nBlockAlign;
lpDstBuffer := nil;
dwDstBufferSize := 0;
bPending := False;
bQueued := False;
bFreeSrcBuffer := False;
if not acmInitConvert(Result, pwfxSrc, pwfxDst, RealTime) then
begin
acmDoneConvert(Result);
exit;
end;
{$IFDEF USEWAVEMPEG}
if (lpSrcBuffer = nil) then
begin
lpSrcBuffer := GlobalAllocMem(dwSrcBufferSize);
bFreeSrcBuffer := True;
end;
{$ELSE}
if (Streams.Count > 0) then
lpSrcBuffer := PACMStream(Streams[0])^.lpSrcBuffer;
{$ENDIF}
end;
end;
end;
{-------------------------------------------------------------------------}
function acmDoConvert(pConvert: PACMConvert; SrcBufSize: Longint): Longint;
var
i: integer;
nConvert: Longint;
{$IFDEF USEWAVEMPEG}
info: Tmpgainfo;
Res,nRead,nFree,nFill,nBytes: DWORD;
TryCount: Longint;
{$ENDIF}
begin
Result := -1;
if (pConvert <> nil) then
with pConvert^ do
begin
nConvert := 0;
{$IFDEF USEWAVEMPEG}
if not bUseL3Decoder and not bUseL2Decoder then
{$ENDIF}
begin
nConvert := Min(SrcBufSize,dwSrcBufferSize);
bPending := False;
bQueued := False;
for i := 0 to Streams.Count-1 do
with PACMStream(Streams[i])^,PACMStream(Streams[i])^.acmStreamHeader do
begin
if (dwRemaining > 0) then
begin
{ copy the reamaining bytes to the start }
GlobalMoveMem(pbSrc^,(pbSrc+dwRemaining)^,nConvert);
GlobalMoveMem(((pbSrc+dwSrcUser)-dwRemaining)^,pbSrc^,dwRemaining);
cbSrcLength := nConvert+dwRemaining;
end
else cbSrcLength := nConvert;
if acmStreamConvert(acmStream, @acmStreamHeader,
ACM_STREAMCONVERTF_BLOCKALIGN) = 0 then
begin
{ wait until the converting is done }
while (fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;
nConvert := cbDstLengthUsed;
dwRemaining := cbSrcLength-cbSrcLengthUsed;
if (dwRemaining > 0) then
begin
{ move the remaining bytes to the end of the buffer }
GlobalMoveMem((pbSrc+cbSrcLengthUsed)^,(pbSrc+dwSrcUser-dwRemaining)^,dwRemaining);
bPending := True;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -