MMACMSup.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:36k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 27.01.99 - 02:33:52 $                                        =}
  24. {========================================================================}
  25. unit MMACMSup;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     Classes,
  37.     Forms,
  38.     MMSystem,
  39.     MMUtils,
  40.     MMRegs,
  41.     MMPCMSup,
  42.     MMACM
  43.     {$IFDEF USEWAVEMPEG}
  44.     ,L3DecDLL,
  45.     L2DecDLL
  46.     {$ENDIF}
  47.     ;
  48. type
  49.    PACMStream  = ^TACMStream;
  50.    TACMStream  = packed record
  51.      lpSrcBuffer    : PChar;
  52.      lpDstBuffer    : PChar;
  53.      dwSrcBufferSize: Longint;
  54.      dwDstBufferSize: Longint;
  55.      dwRemaining    : Longint;
  56.      acmStream      : THACMSTREAM;
  57.      acmStreamHeader: TACMStreamHeader;
  58.    end;
  59.    PACMConvert = ^TACMConvert;
  60.    TACMConvert = packed record
  61.       lpSrcBuffer      : PChar;
  62.       lpDstBuffer      : PChar;
  63.       dwSrcBufferSize  : Longint;
  64.       dwDstBufferSize  : Longint;
  65.       dwBytesConverted : Longint;
  66.       dwBytesRead      : Longint;
  67.       bPending         : Boolean;
  68.       bQueued          : Boolean;
  69.       bFreeSrcBuffer   : Boolean;
  70.       Streams          : TList;
  71.       {$IFDEF USEWAVEMPEG}
  72.       lpDecBuffer      : array[0..16384-1] of Byte;
  73.       bUseL3Decoder    : Boolean;
  74.       pL3DLL           : THandle;
  75.       bUseL2Decoder    : Boolean;
  76.       pL2DLL           : PL2DLL; 
  77.       DataSection      : TRTLCriticalSection;
  78.       {$ENDIF}
  79.    end;
  80. { a set of low level conversion routines to convert Formats }
  81. function  acmMustConvert(pwfxSrc,pwfxDst: PWaveFormatEx): Boolean;
  82. function  acmQueryConvert(pwfxSrc,pwfxDst: PWaveFormatEx; RealTime: Boolean): Boolean;
  83. function  acmSuggestPCMFormat(pwfxSrc: PWaveFormatEx): TWaveFormatEx;
  84. function  acmSuggestPCMFormatEx(pwfxSrc: PWaveFormatEx; Bits,Channels,SampleRate: Longint): TWaveFormatEx;
  85. function  acmSizeOutputData(pwfxSrc,pwfxDst: PWaveFormatEx; SrcBufSize: Longint): Longint;
  86. function  acmBeginConvert(pwfxSrc,pwfxDst: PWaveFormatEx;
  87.                           SrcBuffer: PChar; SrcBufSize: Longint; RealTime: Boolean): PACMConvert;
  88. function  acmDoConvert(pConvert: PACMConvert; SrcBufSize: Longint): Longint;
  89. function  acmFlushConvert(pConvert: PACMConvert): Boolean;
  90. function  acmEndConvert(pConvert: PACMConvert; SrcBufSize: Longint): Longint;
  91. procedure acmDoneConvert(var pConvert: PACMConvert);
  92. implementation
  93. {------------------------------------------------------------------------}
  94. function acmMustConvert(pwfxSrc,pwfxDst: PWaveFormatEx): Boolean;
  95. begin
  96.    Result := ((pwfxSrc <> nil) and (pwfxDst <> nil)) and
  97.               ((pwfxSrc^.wFormatTag <> pwfxDst^.wFormatTag) or
  98.                (pwfxSrc^.wBitsPerSample <> pwfxDst^.wBitsPerSample) or
  99.                (pwfxSrc^.nChannels <> pwfxDst^.nChannels) or
  100.                (pwfxSrc^.nSamplesPerSec <> pwfxDst^.nSamplesPerSec));
  101. end;
  102. {------------------------------------------------------------------------}
  103. function acmSuggestPCMFormat(pwfxSrc: PWaveFormatEx): TWaveFormatEx;
  104. var
  105.    Ready: Boolean;
  106.    dwSuggest: Longint;
  107.    wfx: TWaveFormatEx;
  108. begin
  109.    if (pwfxSrc^.wFormatTag <> WAVE_FORMAT_PCM) then
  110.    begin
  111.       Ready := False;
  112.       try
  113.          FillChar(Result,sizeOf(Result),0);
  114.          FillChar(wfx, sizeOf(wfx),0);
  115.          wfx.wFormatTag := WAVE_FORMAT_PCM;
  116.          dwSuggest := ACM_FORMATSUGGESTF_WFORMATTAG;
  117.          { 'suggest' a PCM format' }
  118.          if acmFormatSuggest(0, pwfxSrc, @wfx, SizeOf(wfx), dwSuggest) <> 0 then
  119.             exit;
  120.          if acmStreamOpen(nil, 0, pwfxSrc, @wfx, nil, 0, 0, ACM_STREAMOPENF_QUERY) <> 0 then
  121.             exit;
  122.          Ready  := True;
  123.          Result := wfx;
  124.       finally
  125.          {$IFDEF USEWAVEMPEG}
  126.          if not Ready then
  127.          begin
  128.             if (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
  129.                (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3) then
  130.             begin
  131.                pcmBuildWaveHeader(@wfx,16,pwfxSrc.nChannels,pwfxSrc.nSamplesPerSec);
  132.                Result := wfx;
  133.             end;
  134.          end;
  135.          {$ENDIF}
  136.       end;
  137.    end
  138.    else Result := pwfxSrc^;
  139. end;
  140. {------------------------------------------------------------------------}
  141. function acmSuggestPCMFormatEx(pwfxSrc: PWaveFormatEx; Bits,Channels,SampleRate: Longint): TWaveFormatEx;
  142. var
  143.    Ready: Boolean;
  144.    dwSuggest: Longint;
  145.    wfx: TWaveFormatEx;
  146. begin
  147.    Result := pwfxSrc^;
  148.    if (pwfxSrc^.wFormatTag <> WAVE_FORMAT_PCM) or
  149.       ((Bits > 0) and (pwfxSrc^.wBitsPerSample <> Bits)) or
  150.       ((Channels > 0) and (pwfxSrc^.nChannels <> Channels)) or
  151.       ((SampleRate > 0) and (pwfxSrc^.nSamplesPerSec <> SampleRate)) then
  152.    begin
  153.       Ready := False;
  154.       try
  155.          wfx.wFormatTag := WAVE_FORMAT_PCM;
  156.          dwSuggest := ACM_FORMATSUGGESTF_WFORMATTAG;
  157.          if (Bits > 0) then
  158.          begin
  159.             wfx.wBitsPerSample := Bits;
  160.             dwSuggest := ACM_FORMATSUGGESTF_WBITSPERSAMPLE;
  161.          end;
  162.          if (Channels > 0) then
  163.          begin
  164.             wfx.nChannels := Channels;
  165.             dwSuggest := ACM_FORMATSUGGESTF_NCHANNELS;
  166.          end;
  167.          if (SampleRate > 0) then
  168.          begin
  169.             wfx.nSamplesPerSec := SampleRate;
  170.             dwSuggest := ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
  171.          end;
  172.          { 'suggest' a PCM format' }
  173.          if acmFormatSuggest(0, pwfxSrc, @wfx, SizeOf(wfx), dwSuggest) <> 0 then
  174.             exit;
  175.          if acmStreamOpen(nil, 0, pwfxSrc, @wfx, nil, 0, 0, ACM_STREAMOPENF_QUERY) <> 0 then
  176.             exit;
  177.          Ready := True;
  178.          Result := wfx;
  179.       finally
  180.          {$IFDEF USEWAVEMPEG}
  181.          if not Ready then
  182.          begin
  183.             if (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
  184.                (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3) then
  185.             begin
  186.                pcmBuildWaveHeader(@wfx,Bits,Channels,SampleRate);
  187.             end;
  188.          end;
  189.          {$ENDIF}
  190.       end;
  191.    end;
  192. end;
  193. {------------------------------------------------------------------------}
  194. function acmQueryConvert(pwfxSrc,pwfxDst: PWaveFormatEx; RealTime: Boolean): Boolean;
  195. Label Ready;
  196. var
  197.    Buf: array[0..1024] of Char;
  198.    pwfx: PWaveFormatEx;
  199.    dwSuggest,dwFlags: Longint;
  200. begin
  201.    Result := False;
  202.    if acmDLLLoaded and (HiWord(acmGetVersion) >= $0200) and
  203.       (pwfxSrc <> nil) and (pwfxSrc <> nil) then
  204.    begin
  205.       if acmMustConvert(pwfxSrc,pwfxDst) then
  206.       begin
  207.          dwFlags := ACM_STREAMOPENF_QUERY;
  208.          if not RealTime then dwFlags := dwFlags or ACM_STREAMOPENF_NONREALTIME;
  209.          if (acmStreamOpen(nil, 0, pwfxSrc, pwfxDst, nil, 0, 0, dwFlags) = 0) then
  210.          begin
  211.             Result := True;
  212.             exit;
  213.          end
  214.          {$IFDEF USEWAVEMPEG}
  215.          else if ((pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
  216.                   (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3)) and
  217.                   (pwfxDst.wFormatTag = WAVE_FORMAT_PCM) then
  218.          begin
  219.             if (pwfxSrc^.nSamplesPerSec = pwfxDst.nSamplesPerSec) and
  220.                (pwfxSrc^.nChannels = pwfxDst.nChannels) then
  221.             begin
  222.                Result := True;
  223.                exit;
  224.             end;
  225.          end
  226.          {$ENDIF};
  227.          pwfx := Pointer(@Buf);
  228.          FillChar(pwfx^, sizeOf(pwfx^), 0);
  229.          if (pwfxSrc^.wFormatTag <> WAVE_FORMAT_PCM) then
  230.          begin
  231.             pwfx^.wFormatTag     := WAVE_FORMAT_PCM;
  232.             pwfx^.nChannels      := pwfxDst^.nChannels;
  233.             pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
  234.             dwSuggest            := ACM_FORMATSUGGESTF_WFORMATTAG or
  235.                                     ACM_FORMATSUGGESTF_NCHANNELS or
  236.                                     ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
  237.             { 'suggest' a format' }
  238.             if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
  239.                goto ready;
  240.             dwSuggest           := ACM_FORMATSUGGESTF_WFORMATTAG;
  241.             { 'suggest' a format' }
  242.             if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
  243.                goto ready;
  244.          end
  245.          else if (pwfxSrc^.nChannels <> pwfxDst^.nChannels) or
  246.                  (pwfxSrc^.nSamplesPerSec <> pwfxDst^.nSamplesPerSec) then
  247.          begin
  248.             pwfx^.nChannels      := pwfxDst^.nChannels;
  249.             pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
  250.             dwSuggest            := ACM_FORMATSUGGESTF_NCHANNELS or
  251.                                     ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
  252.             { 'suggest' a format' }
  253.             if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
  254.             begin
  255.                if (acmStreamOpen(nil, 0, pwfx, pwfxDst, nil, 0, 0, dwFlags) = 0) then
  256.                    goto ready;
  257.                if (pwfx^.wBitsperSample = 16) then
  258.                    pwfx^.wBitsPerSample := 8
  259.                else
  260.                    pwfx^.wBitsPerSample := 16;
  261.                dwSuggest := dwSuggest or ACM_FORMATSUGGESTF_WBITSPERSAMPLE;
  262.                if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
  263.                   goto ready;
  264.             end;
  265.          end;
  266.          exit;
  267. Ready:
  268.          if (acmStreamOpen(nil, 0, pwfxSrc, pwfx, nil, 0, 0, dwFlags) <> 0) then
  269.              exit;
  270.          if acmMustConvert(pwfx,pwfxDst) then
  271.             Result := acmQueryConvert(pwfx,pwfxDst,RealTime)
  272.          else
  273.              Result := True;
  274.       end
  275.       else Result := True;
  276.    end;
  277. end;
  278. {-------------------------------------------------------------------------}
  279. function acmSizeOutputData(pwfxSrc,pwfxDst: PWaveFormatEx; SrcBufSize: Longint): Longint;
  280. var
  281.    Ready: Boolean;
  282.    ACMStream: THACMSTREAM;
  283. begin
  284.    Result := -1;
  285.    if (pwfxSrc <> nil) and (pwfxDst <> nil) then
  286.    begin
  287.       Ready := False;
  288.       try
  289.          if acmStreamOpen(@ACMStream, 0, pwfxSrc, pwfxDst, nil, 0, 0, 0) <> 0 then
  290.             exit;
  291.          try
  292.             if acmStreamSize(ACMStream, SrcBufSize, Result, ACM_STREAMSIZEF_SOURCE) <> 0 then
  293.                exit;
  294.             Ready := True;
  295.          finally
  296.             acmStreamClose(ACMStream, 0);
  297.          end;
  298.       finally
  299.          {$IFDEF USEWAVEMPEG}
  300.          if not Ready and ((pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
  301.                            (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3)) then
  302.          begin
  303.             Result := ((SrcBufSize*pwfxDst^.nAvgBytesPerSec) div pwfxSrc^.nAvgBytesPerSec)+4096;
  304.          end;
  305.          {$ENDIF}
  306.       end;
  307.    end;
  308. end;
  309. {------------------------------------------------------------------------}
  310. function acmInitConvert(lpACMConvert: PACMConvert; pwfxSrc,pwfxDst: PWaveFormatEx; RealTime: Boolean): Boolean;
  311. Label Ready;
  312. var
  313.    Buf: array[0..1024] of Char;
  314.    pwfx: PWaveFormatEx;
  315.    dwSuggest,dwFlags: Longint;
  316.    bFreeSrc: Boolean;
  317.    function SetupConvert(pwfxSrc, pwfxDst: PWaveFormatEx; UseMpeg: Boolean): Boolean;
  318.    var
  319.       Stream: PACMStream;
  320.       dwOpenFlags: Longint;
  321.    begin
  322.       Result := False;
  323.       if not UseMpeg then
  324.       begin
  325.          Stream := GlobalAllocMem(sizeOf(TACMStream));
  326.          with Stream^ do
  327.          try
  328.             dwOpenFlags := 0;
  329.             if not RealTime then dwOpenFlags := ACM_STREAMOPENF_NONREALTIME;
  330.             if acmStreamOpen(@acmStream, 0, pwfxSrc, pwfxDst, nil, 0, 0, dwOpenFlags) <> 0 then
  331.                exit;
  332.             if (lpACMConvert^.lpDstBuffer <> nil) then
  333.             begin
  334.                dwSrcBufferSize:= lpACMConvert^.dwDstBufferSize;
  335.                lpSrcBuffer    := lpACMConvert^.lpDstBuffer;
  336.                bFreeSrc       := False;
  337.             end
  338.             else
  339.             begin
  340.                if (lpACMConvert^.lpSrcBuffer = nil) then
  341.                begin
  342.                   dwSrcBufferSize:= 4*lpACMConvert^.dwSrcBufferSize;
  343.                   lpSrcBuffer    := GlobalAllocMem(dwSrcBufferSize);
  344.                   bFreeSrc       := True;
  345.                   lpACMConvert^.bFreeSrcBuffer := True;
  346.                end
  347.                else
  348.                begin
  349.                   dwSrcBufferSize:= lpACMConvert^.dwSrcBufferSize;
  350.                   lpSrcBuffer    := lpACMConvert^.lpSrcBuffer;
  351.                   bFreeSrc       := False;
  352.                end;
  353.             end;
  354.             if acmStreamSize(acmStream, dwSrcBufferSize, dwDstBufferSize, ACM_STREAMSIZEF_SOURCE) <> 0 then
  355.                exit;
  356.             lpDstBuffer := GlobalAllocMem(dwDstBufferSize);
  357.             { setup the first stream header structure }
  358.             with acmStreamHeader do
  359.             begin
  360.                cbStruct        := sizeof(TACMStreamHeader);
  361.                fdwStatus       := 0;
  362.                dwUser          := 0;
  363.                pbSrc           := lpSrcBuffer;
  364.                cbSrcLength     := dwSrcBufferSize;
  365.                cbSrcLengthUsed := 0;
  366.                dwSrcUser       := dwSrcBufferSize;
  367.                pbDst           := lpDstBuffer;
  368.                cbDstLength     := dwDstBufferSize;
  369.                cbDstLengthUsed := 0;
  370.                dwDstUser       := dwDstBufferSize;
  371.             end;
  372.             dwRemaining := 0;
  373.             if acmStreamPrepareHeader(acmStream, @acmStreamHeader, 0) <> 0 then
  374.                exit;
  375.             lpACMConvert^.lpDstBuffer     := lpDstBuffer;
  376.             lpACMConvert^.dwDstBufferSize := dwDstBufferSize;
  377.             lpACMConvert^.Streams.Add(Stream);
  378.             Result := True;
  379.          finally
  380.             if not Result then
  381.             begin
  382.                acmStreamUnprepareHeader(acmStream, @acmStreamHeader, 0);
  383.                acmStreamClose(acmStream, 0);
  384.                if bFreeSrc then GlobalFreeMem(Pointer(lpSrcBuffer));
  385.                GlobalFreeMem(Pointer(lpDstBuffer));
  386.                GlobalFreeMem(Pointer(Stream));
  387.             end;
  388.          end;
  389.       end
  390.       {$IFDEF USEWAVEMPEG}
  391.       else
  392.       with lpACMConvert^ do
  393.       begin
  394.          try
  395.             if (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3) then
  396.             begin
  397.                bUseL3Decoder := True;
  398.                pL3DLL          := mp3DecInit;
  399.                if (pL3DLL = 0) then exit;
  400.                dwDstBufferSize := 2*((dwSrcBufferSize*pwfxDst^.nAvgBytesPerSec) div pwfxSrc^.nAvgBytesPerSec);
  401.                lpDstBuffer     := GlobalAllocMem(dwDstBufferSize);
  402.                if mp3DecOpenEx(pL3DLL,@lpDecBuffer,sizeOf(lpDecBuffer),0,0,0,False) <> 0 then
  403.                begin
  404.                   Result := False;
  405.                   exit;
  406.                end;
  407.                { create critical section object }
  408.                FillChar(DataSection, SizeOf(DataSection), 0);
  409.                InitializeCriticalSection(DataSection);
  410.             end
  411.             else
  412.             begin
  413.                bUseL2Decoder := True;
  414.                pL2DLL          := CreateL2DLLInstance;
  415.                if (pL2DLL = nil) then exit;
  416.                dwDstBufferSize := ((dwSrcBufferSize*pwfxDst^.nAvgBytesPerSec) div pwfxSrc^.nAvgBytesPerSec)+4096;
  417.                lpDstBuffer     := GlobalAllocMem(dwDstBufferSize);
  418.                if (pL2DLL.mpegOpen('external://', 0, 0,0, 0) <> 0) then
  419.                begin
  420.                   Result := False;
  421.                   exit;
  422.                end;
  423.                pL2DLL.mpegCommand(0, MP3_KEY, 0, 0, MP3_KEY_STR);
  424.                { create critical section object }
  425.                FillChar(DataSection, SizeOf(DataSection), 0);
  426.                InitializeCriticalSection(DataSection);
  427.             end;
  428.             Result        := True;
  429.          finally
  430.             if not Result then
  431.             begin
  432.                if (pL3DLL <> 0) then
  433.                begin
  434.                   mp3DecClose(pL3DLL);
  435.                   mp3DecDone(pL3DLL);
  436.                   pL3DLL := 0;
  437.                   GlobalFreeMem(Pointer(lpDstBuffer));
  438.                end;
  439.                if (pl2DLL <> nil) then
  440.                begin
  441.                   pL2DLL.mpegClose;
  442.                   FreeL2DLLInstance(pL2DLL);
  443.                   pL2DLL := nil;
  444.                   GlobalFreeMem(Pointer(lpDstBuffer));
  445.                end;
  446.             end;
  447.          end;
  448.       end
  449.       {$ENDIF};
  450.    end;
  451. begin
  452.    Result := False;
  453.    if acmDLLLoaded and (HiWord(acmGetVersion) >= $0200) and
  454.       (pwfxSrc <> nil) and (pwfxSrc <> nil)  then
  455.    begin
  456.       if acmMustConvert(pwfxSrc,pwfxDst) then
  457.       begin
  458.          dwFlags := ACM_STREAMOPENF_QUERY;
  459.          if not RealTime then dwFlags := dwFlags or ACM_STREAMOPENF_NONREALTIME;
  460.          {$IFDEF USEWAVEMPEG}
  461.          if ((pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG) or
  462.              (pwfxSrc.wFormatTag = WAVE_FORMAT_MPEG_LAYER3)) and
  463.              (pwfxDst.wFormatTag = WAVE_FORMAT_PCM) then
  464.          begin
  465.             if (pwfxSrc^.nSamplesPerSec = pwfxDst.nSamplesPerSec) and
  466.                (pwfxSrc^.nChannels = pwfxDst.nChannels) then
  467.             begin
  468.                Result := SetupConvert(pwfxSrc,pwfxDst,True);
  469.                exit;
  470.             end;
  471.          end
  472.          {$ENDIF};
  473.          if (acmStreamOpen(nil, 0, pwfxSrc, pwfxDst, nil, 0, 0, dwFlags) = 0) then
  474.          begin
  475.             Result := SetupConvert(pwfxSrc,pwfxDst,False);
  476.             exit;
  477.          end;
  478.          pwfx := Pointer(@Buf);
  479.          FillChar(pwfx^, sizeOf(pwfx^), 0);
  480.          if (pwfxSrc^.wFormatTag <> WAVE_FORMAT_PCM) then
  481.          begin
  482.             pwfx^.wFormatTag     := WAVE_FORMAT_PCM;
  483.             pwfx^.nChannels      := pwfxDst^.nChannels;
  484.             pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
  485.             dwSuggest            := ACM_FORMATSUGGESTF_WFORMATTAG or
  486.                                     ACM_FORMATSUGGESTF_NCHANNELS or
  487.                                     ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
  488.             { 'suggest' a format' }
  489.             if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
  490.                goto ready;
  491.             dwSuggest           := ACM_FORMATSUGGESTF_WFORMATTAG;
  492.             { 'suggest' a format' }
  493.             if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
  494.                goto ready;
  495.          end
  496.          else if (pwfxSrc^.nChannels <> pwfxDst^.nChannels) or
  497.                  (pwfxSrc^.nSamplesPerSec <> pwfxDst^.nSamplesPerSec) then
  498.          begin
  499.             pwfx^.nChannels      := pwfxDst^.nChannels;
  500.             pwfx^.nSamplesPerSec := pwfxDst^.nSamplesPerSec;
  501.             dwSuggest            := ACM_FORMATSUGGESTF_NCHANNELS or
  502.                                     ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
  503.             { 'suggest' a format' }
  504.             if acmFormatSuggest(0, pwfxSrc, pwfx, SizeOf(Buf), dwSuggest) = 0 then
  505.             begin
  506.                if (acmStreamOpen(nil, 0, pwfx, pwfxDst, nil, 0, 0, dwFlags) = 0) then
  507.                    goto ready;
  508.                if (pwfx^.wBitsperSample = 16) then
  509.                    pwfx^.wBitsPerSample := 8
  510.                else
  511.                    pwfx^.wBitsPerSample := 16;
  512.                dwSuggest := dwSuggest or ACM_FORMATSUGGESTF_WBITSPERSAMPLE;
  513.                if acmFormatSuggest(0, pwfxSrc, pwfx, sizeOf(Buf), dwSuggest) = 0 then
  514.                   goto ready;
  515.             end;
  516.          end;
  517.          exit;
  518. Ready:
  519.          if (acmStreamOpen(nil, 0, pwfxSrc, pwfx, nil, 0, 0, dwFlags) <> 0) then
  520.              exit;
  521.          Result := SetupConvert(pwfxSrc,pwfx,False);
  522.          if Result and acmMustConvert(pwfx,pwfxDst) then
  523.             Result := acmInitConvert(lpACMConvert,pwfx,pwfxDst,RealTime);
  524.       end;
  525.    end;
  526. end;
  527. {-------------------------------------------------------------------------}
  528. function acmBeginConvert(pwfxSrc,pwfxDst: PWaveFormatEx;
  529.                          SrcBuffer: PChar; SrcBufSize: Longint;
  530.                          RealTime: Boolean): PACMConvert;
  531. begin
  532.    if acmDLLLoaded and (HiWord(acmGetVersion) >= $0200) and
  533.          (pwfxSrc <> nil) and (pwfxDst <> nil) then
  534.    begin
  535.       Result := GlobalAllocMem(sizeOf(TACMConvert));
  536.       with Result^ do
  537.       begin
  538.          Streams          := TList.Create;
  539.          lpSrcBuffer      := SrcBuffer;
  540.          dwSrcBufferSize  := (SrcBufSize div pwfxSrc^.nBlockAlign)*pwfxSrc^.nBlockAlign;
  541.          lpDstBuffer      := nil;
  542.          dwDstBufferSize  := 0;
  543.          bPending         := False;
  544.          bQueued          := False;
  545.          bFreeSrcBuffer   := False;
  546.          if not acmInitConvert(Result, pwfxSrc, pwfxDst, RealTime) then
  547.          begin
  548.             acmDoneConvert(Result);
  549.             exit;
  550.          end;
  551.          {$IFDEF USEWAVEMPEG}
  552.          if (lpSrcBuffer = nil) then
  553.          begin
  554.             lpSrcBuffer := GlobalAllocMem(dwSrcBufferSize);
  555.             bFreeSrcBuffer := True;
  556.          end;
  557.          {$ELSE}
  558.          if (Streams.Count > 0) then
  559.              lpSrcBuffer := PACMStream(Streams[0])^.lpSrcBuffer;
  560.          {$ENDIF}
  561.       end;
  562.    end;
  563. end;
  564. {-------------------------------------------------------------------------}
  565. function acmDoConvert(pConvert: PACMConvert; SrcBufSize: Longint): Longint;
  566. var
  567.    i: integer;
  568.    nConvert: Longint;
  569.    {$IFDEF USEWAVEMPEG}
  570.    info: Tmpgainfo;
  571.    Res,nRead,nFree,nFill,nBytes: DWORD;
  572.    TryCount: Longint;
  573.    {$ENDIF}
  574. begin
  575.    Result := -1;
  576.    if (pConvert <> nil) then
  577.    with pConvert^ do
  578.    begin
  579.       nConvert := 0;
  580.       {$IFDEF USEWAVEMPEG}
  581.       if not bUseL3Decoder and not bUseL2Decoder then
  582.       {$ENDIF}
  583.       begin
  584.          nConvert := Min(SrcBufSize,dwSrcBufferSize);
  585.          bPending := False;
  586.          bQueued  := False;
  587.          for i := 0 to Streams.Count-1 do
  588.          with PACMStream(Streams[i])^,PACMStream(Streams[i])^.acmStreamHeader do
  589.          begin
  590.             if (dwRemaining > 0) then
  591.             begin
  592.                { copy the reamaining bytes to the start }
  593.                GlobalMoveMem(pbSrc^,(pbSrc+dwRemaining)^,nConvert);
  594.                GlobalMoveMem(((pbSrc+dwSrcUser)-dwRemaining)^,pbSrc^,dwRemaining);
  595.                cbSrcLength := nConvert+dwRemaining;
  596.             end
  597.             else cbSrcLength := nConvert;
  598.             if acmStreamConvert(acmStream, @acmStreamHeader,
  599.                                 ACM_STREAMCONVERTF_BLOCKALIGN) = 0 then
  600.             begin
  601.                { wait until the converting is done }
  602.                while (fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;
  603.                nConvert := cbDstLengthUsed;
  604.                dwRemaining := cbSrcLength-cbSrcLengthUsed;
  605.                if (dwRemaining > 0) then
  606.                begin
  607.                   { move the remaining bytes to the end of the buffer }
  608.                   GlobalMoveMem((pbSrc+cbSrcLengthUsed)^,(pbSrc+dwSrcUser-dwRemaining)^,dwRemaining);
  609.                   bPending := True;
  610.                end
  611.                else
  612.                begin
  613.                   if (nConvert = 0) and (cbSrcLengthUsed > 0) then
  614.                       bQueued := True;
  615.                   end;
  616.             end
  617.             else exit;
  618.          end;
  619.       end
  620.       {$IFDEF USEWAVEMPEG}
  621.       else if bUseL3Decoder then
  622.       begin
  623.          EnterCriticalSection(DataSection);
  624.          try
  625.             nBytes := SrcBufSize;
  626.             mp3DecGetInputFree(pL3DLL, @nFree);
  627.             mp3DecFill(pL3DLL,lpSrcBuffer, Min(nBytes,nFree), @nFill);
  628.             dec(nBytes,nFill);
  629.             nConvert := 0;
  630.             nRead    := 0;
  631.             bQueued  := True;
  632.             TryCount := 0;
  633.             while True do
  634.             begin
  635.                inc(TryCount);
  636.                Res := mp3DecDecode(pL3DLL, (lpDstBuffer+nConvert), dwDstBufferSize-nConvert, @nRead, @info);
  637.                case Res of
  638.                         MPGA_WARNING_SYNCEOF: break;
  639.                    MPGA_WARNING_SYNCNEEDDATA: begin
  640.                                                  if (nBytes > 0) then
  641.                                                  begin
  642.                                                     mp3DecGetInputFree(pL3DLL, @nFree);
  643.                                                     mp3DecFill(pL3DLL,lpSrcBuffer+(SrcBufSize-nBytes), Min(nBytes,nFree), @nFill);
  644.                                                     dec(nBytes,nFill);
  645.                                                  end
  646.                                                  else break;
  647.                                               end;
  648.                      MPGA_WARNING_SYNCSEARCH: begin
  649.                                                  if (nConvert > 0) then
  650.                                                      break
  651.                                                  else
  652.                                                  begin
  653.                                                     if (TryCount > 100) then exit;
  654.                                                     continue;
  655.                                                  end;
  656.                                               end;
  657.                        MPGA_WARNING_SYNCLOST: continue;
  658.                                      MPGA_OK: begin
  659.                                                  inc(nConvert,nRead);
  660.                                               end;
  661.                        else break;
  662.                end;
  663.             end;
  664.          finally
  665.             if (nBytes > 0) then
  666.             begin
  667.                mp3DecGetInputFree(pL3DLL, @nFree);
  668.                mp3DecFill(pL3DLL,lpSrcBuffer+(SrcBufSize-nBytes), Min(nBytes,nFree), @nFill);
  669.                dec(nBytes,nFill);
  670.             end;
  671.             LeaveCriticalSection(DataSection);
  672.          end;
  673.       end
  674.       else if bUseL2Decoder then
  675.       begin
  676.          EnterCriticalSection(DataSection);
  677.          try
  678.             pL2DLL.mpegCommand(0,CMD_EXTERNALIO_FILL,integer(lpSrcBuffer),SrcBufSize,@nRead);
  679.             nConvert := 0;
  680.             nRead    := 0;
  681.             bQueued  := True;
  682.             TryCount := 0;
  683.             while True do
  684.             begin
  685.                inc(TryCount);
  686.                Res := pL2DLL.mpegGetFrame((lpDstBuffer+nConvert), @nRead, @info);
  687.                case Res of
  688.                         MPGA_WARNING_SYNCEOF: break;
  689.                    MPGA_WARNING_SYNCNEEDDATA: begin
  690.                                                  break;
  691.                                               end;
  692.                      MPGA_WARNING_SYNCSEARCH: begin
  693.                                                if (nConvert > 0) then
  694.                                                    break
  695.                                                else
  696.                                                begin
  697.                                                   if (TryCount > 100) then exit;
  698.                                                   continue;
  699.                                                end;
  700.                                               end;
  701.                        MPGA_WARNING_SYNCLOST: continue;
  702.                                      MPGA_OK: begin
  703.                                                  inc(nConvert,nRead);
  704.                                               end;
  705.                       else break;
  706.                end;
  707.                Sleep(1);
  708.             end;
  709.          finally
  710.             LeaveCriticalSection(DataSection);
  711.          end;
  712.       end
  713.       {$ENDIF};
  714.       Result           := nConvert;
  715.       dwBytesConverted := nConvert;
  716.       dwBytesRead      := 0;
  717.    end;
  718. end;
  719. {-------------------------------------------------------------------------}
  720. function  acmFlushConvert(pConvert: PACMConvert): Boolean;
  721. var
  722.    i: integer;
  723. begin
  724.    Result := False;
  725.    if (pConvert <> nil) then
  726.    with pConvert^ do
  727.    begin
  728.       dwBytesRead := dwBytesConverted;
  729.       bPending    := False;
  730.       bQueued     := False;
  731.       {$IFDEF USEWAVEMPEG}
  732.       if not bUseL3Decoder and not bUseL2Decoder then
  733.       {$ENDIF}
  734.       begin
  735.          for i := 0 to Streams.Count-1 do
  736.          with PACMStream(Streams[i])^,PACMStream(Streams[i])^.acmStreamHeader do
  737.          begin
  738.             dwRemaining := 0;
  739.             cbSrcLength := 0;
  740.             acmStreamConvert(acmStream, @acmStreamHeader,
  741.                              ACM_STREAMCONVERTF_START or ACM_STREAMCONVERTF_END);
  742.          end;
  743.          Result := True;
  744.       end
  745.       {$IFDEF USEWAVEMPEG}
  746.       else if bUseL3Decoder then
  747.       begin
  748.          if (pL3DLL <> 0) then
  749.          begin
  750.             EnterCriticalSection(DataSection);
  751.             try
  752.                if (mp3DecReset(pL3DLL, 0) <> 0) then
  753.                begin
  754.                   Result := False;
  755.                   exit;
  756.                end;
  757.                Result := True;
  758.             finally
  759.                LeaveCriticalSection(DataSection);
  760.             end;
  761.          end;
  762.       end
  763.       else if bUseL2Decoder then
  764.       begin
  765.          if (pL2DLL <> nil) then
  766.          begin
  767.             EnterCriticalSection(DataSection);
  768.             try
  769.                pL2DLL.mpegClose;
  770.                if (pL2DLL.mpegOpen('external://', 0, 0,0, 0) <> 0) then
  771.                begin
  772.                   Result := False;
  773.                   exit;
  774.                end;
  775.                pL2DLL.mpegCommand(0, MP3_KEY, 0, 0, MP3_KEY_STR);
  776.                Result := True;
  777.             finally
  778.                LeaveCriticalSection(DataSection);
  779.             end;
  780.          end;
  781.       end
  782.       {$ENDIF};
  783.    end;
  784. end;
  785. {-------------------------------------------------------------------------}
  786. function  acmEndConvert(pConvert: PACMConvert; SrcBufSize: Longint): Longint;
  787. var
  788.    i: integer;
  789.    nConvert: Longint;
  790.    {$IFDEF USEWAVEMPEG}
  791.    info: Tmpgainfo;
  792.    Res,nRead: DWORD;
  793.    {$ENDIF}
  794. begin
  795.    Result := -1;
  796.    if (pConvert <> nil) then
  797.    with pConvert^ do
  798.    begin
  799.       nConvert := 0;
  800.       {$IFDEF USEWAVEMPEG}
  801.       if not bUseL3Decoder and not bUseL2Decoder then
  802.       {$ENDIF}
  803.       begin
  804.          nConvert := Min(SrcBufSize,dwSrcBufferSize);
  805.          bPending := False;
  806.          for i := 0 to Streams.Count-1 do
  807.          with PACMStream(Streams[i])^,PACMStream(Streams[i])^.acmStreamHeader do
  808.          begin
  809.             if (dwRemaining > 0) then
  810.             begin
  811.                { copy the reamaining bytes to the start }
  812.                GlobalMoveMem(pbSrc^,(pbSrc+dwRemaining)^,nConvert);
  813.                GlobalMoveMem(((pbSrc+dwSrcUser)-dwRemaining)^,pbSrc^,dwRemaining);
  814.                cbSrcLength := nConvert+dwRemaining;
  815.             end
  816.             else cbSrcLength := nConvert;
  817.             if acmStreamConvert(acmStream, @acmStreamHeader,
  818.                                 ACM_STREAMCONVERTF_END) = 0 then
  819.             begin
  820.                { wait until the converting is done }
  821.                while (fdwStatus and ACMSTREAMHEADER_STATUSF_DONE = 0) do;
  822.                nConvert := cbDstLengthUsed;
  823.                dwRemaining := cbSrcLength-cbSrcLengthUsed;
  824.                if (dwRemaining > 0) then
  825.                begin
  826.                   { move the remaining bytes to the end of the buffer }
  827.                   GlobalMoveMem((pbSrc+cbSrcLengthUsed)^,(pbSrc+dwSrcUser-dwRemaining)^,dwRemaining);
  828.                   bPending := True;
  829.                end;
  830.             end
  831.             else exit;
  832.          end;
  833.       end
  834.       {$IFDEF USEWAVEMPEG}
  835.       else if bUseL3Decoder then
  836.       begin
  837.          EnterCriticalSection(DataSection);
  838.          try
  839.             mp3DecSetInputEof(pL3DLL);
  840.             nConvert := 0;
  841.             nRead    := 0;
  842.             while True do
  843.             begin
  844.                Res := mp3DecDecode(pL3DLL, (lpDstBuffer+nConvert), dwDstBufferSize-nConvert, @nRead, @info);
  845.                if (Res <> MPGA_OK) then break;
  846.                inc(nConvert,nRead);
  847.             end;
  848.          finally
  849.             LeaveCriticalSection(DataSection);
  850.          end;
  851.       end
  852.       else if bUseL2Decoder then
  853.       begin
  854.          EnterCriticalSection(DataSection);
  855.          try
  856.             pL2DLL.mpegCommand(0,CMD_EXTERNALIO_SETEOF,0,0,nil);
  857.             nConvert := 0;
  858.             nRead    := 0;
  859.             while True do
  860.             begin
  861.                Res := pL2DLL.mpegGetFrame((lpDstBuffer+nConvert), @nRead, @info);
  862.                if (Res <> MPGA_OK) then break;
  863.                inc(nConvert,nRead);
  864.             end;
  865.          finally
  866.             LeaveCriticalSection(DataSection);
  867.          end;
  868.       end;
  869.       {$ENDIF};
  870.       Result           := nConvert;
  871.       dwBytesConverted := nConvert;
  872.       dwBytesRead      := 0;
  873.    end;
  874. end;
  875. {-------------------------------------------------------------------------}
  876. procedure acmDoneConvert(var pConvert: PACMConvert);
  877. var
  878.    i: integer;
  879.    p: Pointer;
  880. begin
  881.    if (pConvert <> nil) then
  882.    with pConvert^ do
  883.    begin
  884.       {$IFDEF USEWAVEMPEG}
  885.       if not bUseL3Decoder and not bUseL2Decoder then
  886.       {$ENDIF}
  887.       begin
  888.          for i := Streams.Count-1 downto 0 do
  889.          with PACMStream(Streams[i])^,PACMStream(Streams[i])^.acmStreamHeader do
  890.          begin
  891.             if (fdwStatus and ACMSTREAMHEADER_STATUSF_PREPARED <> 0) then
  892.             begin
  893.                cbSrcLength := dwSrcUser;
  894.                cbDstLength := dwDstUser;
  895.                acmStreamUnprepareHeader(acmStream, @acmStreamHeader, 0);
  896.                acmStreamClose(acmStream, 0);
  897.             end;
  898.             GlobalFreeMem(Pointer(lpDstBuffer));
  899.             p := Streams[i];
  900.             Streams.Delete(i);
  901.             GlobalFreeMem(p);
  902.          end;
  903.          Streams.Free;
  904.       end
  905.       {$IFDEF USEWAVEMPEG}
  906.       else if bUseL3Decoder then
  907.       begin
  908.          if (pL3DLL <> 0) then
  909.          begin
  910.             EnterCriticalSection(DataSection);
  911.             try
  912.                mp3DecClose(pL3DLL);
  913.                mp3DecDone(pL3DLL);
  914.                pL3DLL := 0;
  915.                GlobalFreeMem(Pointer(lpDstBuffer));
  916.             finally
  917.                LeaveCriticalSection(DataSection);
  918.                DeleteCriticalSection(DataSection);
  919.             end;
  920.          end;
  921.       end
  922.       else if bUseL2Decoder then
  923.       begin
  924.          if (pL2DLL <> nil) then
  925.          begin
  926.             EnterCriticalSection(DataSection);
  927.             try
  928.                pL2DLL.mpegClose;
  929.                FreeL2DLLInstance(pL2DLL);
  930.                pL2DLL := nil;
  931.                GlobalFreeMem(Pointer(lpDstBuffer));
  932.             finally
  933.                LeaveCriticalSection(DataSection);
  934.                DeleteCriticalSection(DataSection);
  935.             end;
  936.          end;
  937.       end
  938.       {$ENDIF};
  939.       if bFreeSrcBuffer then GlobalFreeMem(Pointer(pConvert^.lpSrcBuffer));
  940.    end;
  941.    GlobalFreeMem(Pointer(pConvert));
  942. end;
  943. end.