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

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: 01.11.98 - 04:14:05 $                                        =}
  24. {========================================================================}
  25. unit MMACMCvt;
  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.     Controls,
  38.     MMSystem,
  39.     MMRegs,
  40.     MMObj,
  41.     MMDSPObj,
  42.     MMString,
  43.     MMUtils,
  44.     MMWaveIO,
  45.     MMPCMSup,
  46.     MMACMSup;
  47. type
  48.    EMMConverterError = class(Exception);
  49.    TMMConvertQuality = (cqHigh,cqLow);
  50.    {-- TMMPCMConverter --------------------------------------------------------}
  51.    TMMACMConverter = class(TMMDSPComponent)
  52.    private
  53.       FEnabled     : Boolean;
  54.       FOpen        : Boolean;
  55.       FStarted     : Boolean;
  56.       FCvtBufSize  : Longint;
  57.       FPSrcFormat  : PWaveFormatEx;
  58.       FPDstFormat  : PWaveFormatEx;
  59.       FCvtFormat   : PWaveFormatEx;
  60.       FMustConvert : Boolean;        { the format must be converted    }
  61.       FCanConvert  : Boolean;        { the format can be converted     }
  62.       FPACMConvert : PACMConvert;    { structure for conversion        }
  63.       FMoreBuffers : Boolean;
  64.       FDone        : Boolean;
  65.       FQuality     : TMMConvertQuality;
  66.       Ftwh         : TMMWaveHdr;
  67.       function  GetCanConvert: Boolean;
  68.       procedure PrepareConversion;
  69.    protected
  70.       procedure SuggestFormat; virtual;
  71.       procedure Loaded; override;
  72.       procedure ChangePWaveFormat(aValue: PWaveFormatEx); override;
  73.       procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  74.       procedure Opened; override;
  75.       procedure Closed; override;
  76.       procedure Started; override;
  77.       procedure Stopped; override;
  78.       procedure Reseting; override;
  79.       procedure BufferReady(lpwh: PWaveHdr); override;
  80.       procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  81.    public
  82.       constructor Create(aOwner: TComponent); override;
  83.       destructor Destroy; override;
  84.       procedure Open;
  85.       procedure Close;
  86.       procedure Start;
  87.       procedure Stop;
  88.       property CanConvert: Boolean read GetCanConvert;
  89.    published
  90.       property Input;
  91.       property Output;
  92.       property Enabled: Boolean read FEnabled write FEnabled default True;
  93.       property Quality: TMMConvertQuality read FQuality write FQuality default cqLow;
  94.    end;
  95.    TMMRequiredParam  = (rpBits,rpChannels,rpSampleRate);
  96.    TMMRequiredParams = set of TMMRequiredParam;
  97.    {-- TMMPCMConverter --------------------------------------------------------}
  98.    TMMPCMConverter = class(TMMACMConverter)
  99.    private
  100.       FAutoConvert : Boolean;          { use your params or best match        }
  101.       FBits        : TMMBits;          { bit8 or bit16                        }
  102.       FMode        : TMMMode;          { mMono or mStereo                     }
  103.       FSampleRate  : Longint;          { samplerate 8000..100000              }
  104.       FRequired    : TMMRequiredParams;{ only some of the params are required }
  105.       procedure SetAutoConvert(aValue: Boolean);
  106.       procedure SetSampleRate(Rate: Longint);
  107.       procedure SetBits(aValue: TMMBits);
  108.       procedure SetMode(aValue: TMMMode);
  109.       procedure SetRequired(aValue: TMMRequiredParams);
  110.       procedure SetWaveParams;
  111.    protected
  112.       procedure SuggestFormat; override;
  113.       procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  114.    public
  115.       constructor Create(aOwner: TComponent); override;
  116.    published
  117.       property AutoConvert: Boolean read FAutoConvert write SetAutoConvert default True;
  118.       property SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
  119.       property BitLength: TMMBits read FBits write setBits default b8bit;
  120.       property Mode: TMMMode read FMode write SetMode default mMono;
  121.       property Required: TMMRequiredParams read FRequired write SetRequired;
  122.    end;
  123. implementation
  124. const
  125.      ACM_CONVERT_SIZE = 8192;
  126. {== TMMACMConverter ============================================================}
  127. constructor TMMACMConverter.Create(aOwner: TComponent);
  128. begin
  129.    inherited Create(aOwner);
  130.    FENabled     := True;
  131.    FOpen        := False;
  132.    FStarted     := False;
  133.    FMustConvert := False;
  134.    FCanConvert  := False;
  135.    FPACMConvert := nil;
  136.    FPSrcFormat  := nil;
  137.    FQuality     := cqLow;
  138.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  139.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  140. end;
  141. {-- TMMACMConverter ------------------------------------------------------------}
  142. destructor TMMACMConverter.Destroy;
  143. begin
  144.    Close;
  145.    GlobalFreeMem(Pointer(FPSrcFormat));
  146.    GlobalFreeMem(Pointer(FPDstFormat));
  147.    GlobalFreeMem(Pointer(FCvtFormat));
  148.    inherited Destroy;
  149. end;
  150. {-- TMMACMConverter ------------------------------------------------------------}
  151. procedure TMMACMConverter.Loaded;
  152. begin
  153.    inherited Loaded;
  154.    PrepareConversion;
  155. end;
  156. {-- TMMACMConverter ------------------------------------------------------------}
  157. function TMMACMConverter.GetCanConvert: Boolean;
  158. begin
  159.    Result := (not FMustConvert) or FCanConvert;
  160. end;
  161. {-- TMMACMConverter ------------------------------------------------------------}
  162. procedure TMMACMConverter.ChangePWaveFormat(aValue: PWaveFormatEx);
  163. begin
  164.    if (aValue <> FPSrcFormat) then
  165.    begin
  166.       GlobalFreeMem(Pointer(FPSrcFormat));
  167.       FPSrcFormat := wioCopyWaveFormat(aValue);
  168.       PrepareConversion;
  169.    end;
  170. end;
  171. {-- TMMACMConverter ------------------------------------------------------------}
  172. procedure TMMACMConverter.SetPWaveFormat(aValue: PWaveFormatEx);
  173. begin
  174.    if (aValue <> nil) and not (csLoading in ComponentState) and not (csDestroying in ComponentState) then
  175.    begin
  176.       GlobalFreeMem(Pointer(FPDStFormat));
  177.       FPDstFormat := wioCopyWaveFormat(aValue);
  178.       PrepareConversion;
  179.    end;
  180. end;
  181. {-- TMMACMConverter ------------------------------------------------------------}
  182. procedure TMMACMConverter.SuggestFormat;
  183. begin
  184.    GlobalFreeMem(Pointer(FCvtFormat));
  185.    if FEnabled then
  186.       FCvtFormat := wioCopyWaveFormat(FPDstFormat);
  187. end;
  188. {-- TMMACMConverter ------------------------------------------------------------}
  189. procedure TMMACMConverter.PrepareConversion;
  190. begin
  191.    FMustConvert := False;
  192.    FCanConvert := False;
  193.    if (FPSrcFormat <> nil) and FEnabled then
  194.    begin
  195.       SuggestFormat;
  196.       if acmMustConvert(FPSrcFormat,FCvtFormat) then
  197.       begin
  198.          FMustConvert := True;
  199.          if acmQueryConvert(FPSrcFormat,FCvtFormat,Boolean(FQuality)) then
  200.          begin
  201.             FCanConvert := True;
  202.             inherited SetPWaveFormat(FCvtFormat);
  203.             exit;
  204.          end;
  205.       end;
  206.    end;
  207.    inherited SetPWaveFormat(FPSrcFormat);
  208. end;
  209. {-- TMMACMConverter ------------------------------------------------------------}
  210. procedure TMMACMConverter.Open;
  211. begin
  212.    if not FOpen and FEnabled then
  213.    begin
  214.       if FMustConvert then
  215.       try
  216.          if FCanConvert then
  217.          begin
  218.             FCvtBufSize := Min(ACM_CONVERT_SIZE,Max(BufferSize,Max(QUEUE_READ_SIZE,QUEUE_WRITE_SIZE)));
  219.             { init the conversion structure }
  220.             FPACMConvert := acmBeginConvert(FPSrcFormat,PWaveFormat,nil,FCvtBufSize,Boolean(FQuality));
  221.             if (FPACMConvert = nil) then
  222.             begin
  223.                FCanConvert := False;
  224.                exit;
  225.             end;
  226.          end;
  227.       finally
  228.          if not FCanConvert then
  229.             raise EMMConverterError.Create('Unable to convert to destination format');
  230.       end;
  231.       FOpen := True;
  232.    end;
  233. end;
  234. {-- TMMACMConverter ------------------------------------------------------------}
  235. procedure TMMACMConverter.Close;
  236. begin
  237.    if FOpen then
  238.    begin
  239.       Stop;
  240.       FOpen := False;
  241.       acmDoneConvert(FPACMConvert);
  242.    end;
  243. end;
  244. {-- TMMACMConverter ------------------------------------------------------------}
  245. procedure TMMACMConverter.Start;
  246. begin
  247.    if FOpen and not FStarted then
  248.    begin
  249.       FStarted := True;
  250.       FMoreBuffers := False;
  251.       FDone := False;
  252.    end;
  253. end;
  254. {-- TMMACMConverter ------------------------------------------------------------}
  255. procedure TMMACMConverter.Stop;
  256. begin
  257.    if FStarted then
  258.    begin
  259.       FStarted := False;
  260.       if (FPACMConvert <> nil) then
  261.       with FPACMConvert^ do
  262.       begin
  263.          dwBytesRead := dwBytesConverted;
  264.       end;
  265.    end;
  266. end;
  267. {-- TMMACMConverter ------------------------------------------------------------}
  268. procedure TMMACMConverter.Opened;
  269. begin
  270.    Open;
  271.    inherited Opened;
  272. end;
  273. {-- TMMACMConverter ------------------------------------------------------------}
  274. procedure TMMACMConverter.Closed;
  275. begin
  276.    Close;
  277.    inherited Closed;
  278. end;
  279. {-- TMMACMConverter ------------------------------------------------------------}
  280. procedure TMMACMConverter.Started;
  281. begin
  282.    inherited Started;
  283.    Start;
  284. end;
  285. {-- TMMACMConverter ------------------------------------------------------------}
  286. procedure TMMACMConverter.Stopped;
  287. begin
  288.    Stop;
  289.    inherited Stopped;
  290. end;
  291. {-- TMMACMConverter ------------------------------------------------------------}
  292. procedure TMMACMConverter.Reseting;
  293. begin
  294.    inherited Reseting;
  295.    if (FPACMConvert <> nil) then
  296.    begin
  297.       acmFlushConvert(FPACMConvert);
  298.       FDone := False;
  299.    end;
  300. end;
  301. {-- TMMACMConverter ------------------------------------------------------------}
  302. procedure TMMACMConverter.BufferReady(lpwh: PWaveHdr);
  303. var
  304.    nBytes,nRead,nWrite,nConvert: Longint;
  305. begin
  306.    if FOpen and FStarted then
  307.    begin
  308.       { write Data }
  309.       if (Output <> nil) then
  310.       begin
  311.          if FMustConvert and FCanConvert and (FPACMConvert <> nil) then
  312.          with FPACMConvert^ do
  313.          begin
  314.             nBytes := lpwh^.dwBytesRecorded;
  315.             nRead := 0;
  316.             while FStarted and (nBytes > 0) do
  317.             begin
  318.                nConvert := Min(nBytes,dwSrcBufferSize);
  319.                GlobalMoveMem(PChar(lpwh^.lpData+nRead)^,lpSrcBuffer^,nConvert);
  320.                try
  321.                   if acmDoConvert(FPACMConvert,nConvert) <= 0 then
  322.                   begin
  323.                      if not bPending and not bQueued then
  324.                      begin
  325.                         FCanConvert := False;
  326.                         raise EMMConverterError.Create('Unable to convert to destination format');
  327.                         exit;
  328.                      end;
  329.                   end;
  330.                except
  331.                   FCanConvert := False;
  332.                   raise;
  333.                end;
  334.                dec(nBytes,nConvert);
  335.                inc(nRead,nConvert);
  336.                while FStarted and (dwBytesRead < dwBytesConverted) do
  337.                begin
  338.                   GlobalFillMem(Ftwh,sizeOf(Ftwh),0);
  339.                   nWrite := Min(dwBytesConverted-dwBytesRead,BufferSize);
  340.                   Ftwh.wh.lpData := PChar(lpDstBuffer+dwBytesRead);
  341.                   Ftwh.wh.dwBufferLength := nWrite;
  342.                   Ftwh.wh.dwBytesRecorded:= nWrite;
  343.                   inc(dwBytesRead,nWrite);
  344.                   inherited BufferReady(@Ftwh);
  345.                end;
  346.             end;
  347.          end
  348.          else inherited BufferReady(lpwh);
  349.       end;
  350.    end
  351.    else inherited BufferReady(lpwh);
  352. end;
  353. {-- TMMACMConverter ------------------------------------------------------------}
  354. procedure TMMACMConverter.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  355. Label CopyData;
  356. var
  357.    nRead,nBytes: Longint;
  358.    TryCount: integer;
  359. begin
  360.    if FOpen and FStarted then
  361.    begin
  362.       { read Data }
  363.       if (Input <> nil) then
  364.       begin
  365.          TryCount := 0;
  366.          nBytes   := lpwh^.dwBufferLength;
  367.          if FMustConvert and FCanConvert and (FPACMConvert <> nil) then
  368.          with FPACMConvert^ do
  369.          begin
  370. CopyData:
  371.             { get some data from the conversion buffer }
  372.             if (dwBytesConverted-dwBytesRead > 0) then
  373.             begin
  374.                nRead := Min(dwBytesConverted-dwBytesRead,nBytes);
  375.                GlobalMoveMem((lpDstBuffer+dwBytesRead)^,(lpwh^.lpData+lpwh^.dwBytesRecorded)^,nRead);
  376.                dec(nBytes,nRead);
  377.                inc(dwBytesRead,nRead);
  378.                inc(lpwh^.dwBytesRecorded,nRead);
  379.             end;
  380.             if not PMMWaveHdr(lpwh)^.LoopRec.dwLooping then
  381.             begin
  382.                { do we need more data ? }
  383.                if FStarted and (nBytes > 0) then
  384.                begin
  385.                   if not FDone then
  386.                   begin
  387.                      GlobalFillMem(Ftwh,sizeOf(Ftwh),0);
  388.                      Ftwh.wh.lpData := lpSrcBuffer;
  389.                      Ftwh.wh.dwBufferLength := dwSrcBufferSize;
  390.                      Ftwh.LoopRec := PMMWaveHdr(lpwh)^.LoopRec;
  391.                      FMoreBuffers := False;
  392.                      inherited BufferLoad(@Ftwh,FMoreBuffers);
  393.                      nRead := Ftwh.wh.dwBytesRecorded;
  394.                      PMMWaveHdr(lpwh)^.LoopRec := Ftwh.LoopRec;
  395.                      if not FMoreBuffers or (nRead <= 0) then FDone := True;
  396.                   end
  397.                   else nRead := 0;
  398.                   if (nRead > 0) and FStarted then
  399.                   begin
  400.                      if acmDoConvert(FPACMConvert,nRead) <= 0 then
  401.                      begin
  402.                         if not FDone then
  403.                         begin
  404.                            inc(TryCount);
  405.                            if (TryCount < 5) then goto CopyData;
  406.                            FCanConvert := False;
  407.                            raise EMMConverterError.Create('Unable to convert to destination format');
  408.                            exit;
  409.                         end
  410.                         else
  411.                         begin
  412.                            if (acmEndConvert(FPACMConvert,nRead) > 0) then
  413.                                goto CopyData;
  414.                         end;
  415.                      end
  416.                      else if FStarted then goto CopyData;
  417.                   end
  418.                   else if FStarted then
  419.                   begin
  420.                      if (acmEndConvert(FPACMConvert,0) > 0) then goto CopyData;
  421.                   end;
  422.                end;
  423.             end;
  424.             MoreBuffers := FMoreBuffers or (dwBytesConverted-dwBytesRead > 0) or bPending;
  425.          end
  426.          else inherited BufferLoad(lpwh,MoreBuffers);
  427.       end;
  428.    end
  429.    else inherited BufferLoad(lpwh,MoreBuffers);
  430. end;
  431. {== TMMPCMConverter ============================================================}
  432. constructor TMMPCMConverter.Create(aOwner: TComponent);
  433. begin
  434.    inherited Create(aOwner);
  435.    FAutoConvert := True;
  436.    FSampleRate  := 11025;
  437.    FBits        := b8Bit;
  438.    FMode        := mMono;
  439.    FRequired    := [rpBits,rpChannels,rpSampleRate];
  440.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  441.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  442. end;
  443. {-- TMMPCMConverter ------------------------------------------------------------}
  444. procedure TMMPCMConverter.SuggestFormat;
  445. var
  446.    wfx,wfx2: TWaveFormatEx;
  447. begin
  448.    GlobalFreeMem(Pointer(FCvtFormat));
  449.    if not FEnabled then exit;
  450.    if FAutoConvert and (FPSrcFormat <> nil) then
  451.    begin
  452.       wfx := acmSuggestPCMFormat(FPSrcFormat);
  453.    end
  454.    else
  455.    begin
  456.       if (FPSrcFormat <> nil) then
  457.       begin
  458.          wfx2 := acmSuggestPCMFormat(FPSrcFormat);
  459.          if (rpBits in FRequired) then
  460.              wfx2.wBitsPerSample := (Ord(FBits)+1)*8;
  461.          if (rpChannels in FRequired) then
  462.              wfx2.nChannels := Ord(FMode)+1;
  463.          if (rpSampleRate in FRequired) then
  464.              wfx2.nSamplesPerSec := FSampleRate;
  465.          pcmBuildWaveHeader(@wfx,wfx2.wBitsPerSample,wfx2.nChannels,wfx2.nSamplesPerSec);
  466.       end
  467.       else pcmBuildWaveHeader(@wfx,(Ord(FBits)+1)*8,Ord(FMode)+1,FSampleRate);
  468.    end;
  469.    if (wfx.wFormatTag <> 0) then
  470.        FCvtFormat := wioCopyWaveFormat(@wfx);
  471. end;
  472. {-- TMMPCMConverter ------------------------------------------------------------}
  473. procedure TMMPCMConverter.SetPWaveFormat(aValue: PWaveFormatEx);
  474. begin
  475.    if (aValue <> nil) and not (csLoading in ComponentState) and not (csDestroying in ComponentState) then
  476.    begin
  477.       if not (csDesigning in ComponentState) then
  478.          if not pcmIsValidFormat(aValue) then
  479.             raise EMMConverterError.Create(LoadResStr(IDS_INVALIDFORMAT));
  480.       inherited SetPWaveFormat(aValue);
  481.    end;
  482. end;
  483. {-- TMMPCMConverter ------------------------------------------------------------}
  484. procedure TMMPCMConverter.SetAutoConvert(aValue: Boolean);
  485. begin
  486.    if (aValue <> FAutoConvert) then
  487.    begin
  488.       FAutoConvert := aValue;
  489.       SetWaveParams;
  490.    end;
  491. end;
  492. {-- TMMPCMConverter ------------------------------------------------------------}
  493. procedure TMMPCMConverter.SetWaveParams;
  494. begin
  495.    SuggestFormat;
  496.    if (FCvtFormat <> nil) then
  497.        PWaveFormat := FCvtFormat
  498.    else
  499.        PWaveFormat := FPSrcFormat;
  500. end;
  501. {-- TMMPCMConverter ------------------------------------------------------------}
  502. Procedure TMMPCMConverter.SetRequired(aValue: TMMRequiredParams);
  503. begin
  504.      if (FRequired <> aValue) then
  505.      begin
  506.         FRequired := aValue;
  507.         SetWaveParams;
  508.      end;
  509. end;
  510. {-- TMMPCMConverter ------------------------------------------------------------}
  511. Procedure TMMPCMConverter.SetSampleRate(Rate: Longint);
  512. begin
  513.      if (Rate <> SampleRate) then
  514.      begin
  515.         FSampleRate := MinMax(Rate,8000,88200);
  516.         SetWaveParams;
  517.      end;
  518. end;
  519. {-- TMMPCMConverter ------------------------------------------------------------}
  520. Procedure TMMPCMConverter.SetBits(aValue: TMMBits);
  521. begin
  522.    if (aValue <> FBits) then
  523.    begin
  524.       FBits := aValue;
  525.       SetWaveParams;
  526.    end;
  527. end;
  528. {-- TMMPCMConverter ------------------------------------------------------------}
  529. Procedure TMMPCMConverter.SetMode(aValue: TMMMode);
  530. begin
  531.    if (aValue <> FMode) and (aValue in [mMono,mStereo]) then
  532.    begin
  533.       FMode := aValue;
  534.       SetWaveParams;
  535.    end;
  536.    {$IFDEF WIN32}
  537.    {$IFDEF TRIAL}
  538.    {$DEFINE _HACK1}
  539.    {$I MMHACK.INC}
  540.    {$ENDIF}
  541.    {$ENDIF}
  542. end;
  543. end.