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

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.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: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMFlange;
  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.     IniFiles,
  39.     MMSystem,
  40.     MMRegs,
  41.     MMObj,
  42.     MMDSPObj,
  43.     MMUtils,
  44.     MMMath,
  45.     MMWaveIO,
  46.     MMPCMSup,
  47.     MMFX;
  48. type
  49.    EMMFlangeError = class(Exception);
  50.    {-- TMMFlanger -------------------------------------------------------------}
  51.    TMMFlanger = class(TMMDSPComponent)
  52.    private
  53.       FEnabled       : Boolean;
  54.       FOpen          : Boolean;
  55.       FPFlange       : PFlanger;
  56.       FDescription   : String;
  57.       FDryMix        : TMMEffectVolume;
  58.       FWetMix        : TMMEffectVolume;
  59.       FFeedBack      : TMMFeedBack;
  60.       FMaxDelay      : integer;
  61.       FDelay         : integer;
  62.       FDepth         : Float;
  63.       FRate          : Float;
  64.       FCleanup       : Longint;
  65.       FOnChange      : TNotifyEvent;
  66.       FOnPcmOverflow : TNotifyEvent;
  67.       procedure SetDescription(aValue: String);
  68.       procedure SetEnabled(aValue: Boolean);
  69.       procedure SetGains(index: integer; aValue: TMMEffectVolume);
  70.       procedure SetFeedBack(aValue: TMMFeedBack);
  71.       procedure SetDelays(index: integer; aValue: integer);
  72.       procedure SetDepth(aValue: Float);
  73.       procedure SetRate(aValue: Float);
  74.    protected
  75.       procedure Assign(Source: TPersistent); override;
  76.       procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  77.       procedure Change; dynamic;
  78.       procedure Update; virtual;
  79.       procedure Opened; override;
  80.       procedure Closed; override;
  81.       procedure Started; override;
  82.       procedure PcmOverflow; dynamic;
  83.       procedure BufferReady(lpwh: PWaveHdr); override;
  84.       procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  85.    public
  86.       constructor Create(aOwner: TComponent); override;
  87.       destructor Destroy; override;
  88.       procedure SaveToIniFile(IniFile: TFileName; Section: string);
  89.       procedure ReadFromIniFile(IniFile: TFileName; Section: string);
  90.       procedure ReadIniSections(IniFile: TFileName; Strings: TStrings);
  91.       procedure DeleteSection(IniFile: TFileName; Section: string);
  92.       procedure Open;
  93.       procedure Close;
  94.       procedure Process(Buffer: PChar; Length: integer);
  95.       function  CleanUp(Buffer: PChar; Length: integer): Longint;
  96.    published
  97.       property OnChange: TNotifyEvent read FOnChange write FOnChange;
  98.       property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
  99.       property Input;
  100.       property Output;
  101.       property Enabled: Boolean read FEnabled write SetEnabled default True;
  102.       property Description: String read FDescription write SetDescription;
  103.       property DryMix: TMMEffectVolume index 0 read FDryMix write SetGains;
  104.       property WetMix: TMMEffectVolume index 1 read FWetMix write SetGains;
  105.       property FeedBack: TMMFeedBack read FFeedback write SetFeedBack;
  106.       property MaxDelay: integer index 0 read FMaxDelay write SetDelays;
  107.       property Delay: integer index 1 read FDelay write SetDelays;
  108.       property Depth: Float read FDepth write SetDepth;
  109.       property Rate: Float read FRate write SetRate;
  110.    end;
  111. implementation
  112. {== TMMFlanger ============================================================}
  113. constructor TMMFlanger.Create(aOwner: TComponent);
  114. begin
  115.    inherited Create(aOwner);
  116.    FEnabled     := True;
  117.    FOpen        := False;
  118.    FPFlange     := nil;
  119.    FDescription := 'Untitled';
  120.    FDryMix      := 50;
  121.    FWetMix      := 50;
  122.    FFeedBack    := 0;
  123.    FMaxDelay    := 250;
  124.    FDelay       := 1;
  125.    FDepth       := 0;
  126.    FRate        := 0;
  127. end;
  128. {-- TMMFlanger ------------------------------------------------------------}
  129. destructor TMMFlanger.Destroy;
  130. begin
  131.    Close;
  132.    inherited Destroy;
  133. end;
  134. {-- TMMFlanger ------------------------------------------------------------}
  135. procedure TMMFlanger.Assign(Source: TPersistent);
  136. begin
  137.    if (Source is TMMFlanger) then
  138.    begin
  139.       if (Source <> nil) then
  140.       begin
  141.          Enabled    := TMMFlanger(Source).Enabled;
  142.          Description:= TMMFlanger(Source).Description;
  143.          DryMix     := TMMFlanger(Source).DryMix;
  144.          WetMix     := TMMFlanger(Source).WetMix;
  145.          FeedBack   := TMMFlanger(Source).FeedBack;
  146.          MaxDelay   := TMMFlanger(Source).MaxDelay;
  147.          Delay      := TMMFlanger(Source).Delay;
  148.          Depth      := TMMFlanger(Source).Depth;
  149.          Rate       := TMMFlanger(Source).Rate;
  150.       end;
  151.    end;
  152. end;
  153. {-- TMMFlanger ------------------------------------------------------------}
  154. procedure TMMFlanger.PcmOverflow;
  155. begin
  156.    if assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
  157. end;
  158. {-- TMMFlanger ------------------------------------------------------------}
  159. procedure TMMFlanger.Change;
  160. begin
  161.    if assigned(FOnChange) then FOnChange(Self);
  162. end;
  163. {-- TMMFlanger ------------------------------------------------------------}
  164. procedure TMMFlanger.SaveToIniFile(IniFile: TFileName; Section: string);
  165. begin
  166.    if (IniFile <> '') then
  167.    begin
  168.       with TIniFile.Create(IniFile) do
  169.       try
  170.          if Pos('Flanger.',Section) = 0 then Section := 'Flanger.'+Section;
  171.          WriteInteger(Section, 'DryMix', DryMix);
  172.          WriteInteger(Section, 'WetMix', WetMix);
  173.          WriteInteger(Section, 'FeedBack', FeedBack);
  174.          WriteInteger(Section, 'MaxDelay', MaxDelay);
  175.          WriteInteger(Section, 'Delay', Delay);
  176.          WriteString(Section, 'Depth', FloatToStr(Depth));
  177.          WriteString(Section, 'Rate', FloatToStr(Rate));
  178.       finally
  179.          Free;
  180.       end;
  181.    end;
  182. end;
  183. {-- TMMFlanger ------------------------------------------------------------}
  184. procedure TMMFlanger.ReadFromIniFile(IniFile: TFileName; Section: string);
  185. var
  186.    i,P: integer;
  187. begin
  188.    if (IniFile <> '') then
  189.    begin
  190.       with TIniFile.Create(IniFile) do
  191.       try
  192.          if Pos('Flanger.',Section) = 0 then Section := 'Flanger.'+Section;
  193.          i := ReadInteger(Section, 'MaxDelay', -1);
  194.          if (i > 0) then
  195.          begin
  196.             DryMix      := ReadInteger(Section, 'DryMix', 50);
  197.             WetMix      := ReadInteger(Section, 'WetMix', 50);
  198.             FeedBack    := ReadInteger(Section, 'FeedBack', 0);
  199.             MaxDelay    := ReadInteger(Section, 'MaxDelay', 250);
  200.             Delay       := ReadInteger(Section, 'Delay', 1);
  201.             Depth       := StrToFloat(ReadString(Section, 'Depth', '4.0'));
  202.             Rate        := StrToFloat(ReadString(Section, 'Rate', '1.0'));
  203.             P := Pos('.',Section);
  204.             if (P <> 0) then Section := Copy(Section,P+1,MaxInt);
  205.             Description := Section;
  206.          end;
  207.       finally
  208.          Free;
  209.       end;
  210.    end;
  211. end;
  212. {-- TMMFlanger ------------------------------------------------------------}
  213. procedure TMMFlanger.ReadIniSections(IniFile: TFileName; Strings: TStrings);
  214. var
  215.    i, P: integer;
  216.    Sections: TStringList;
  217. begin
  218.    if (IniFile <> '') and (Strings <> nil) then
  219.    begin
  220.       with TIniFile.Create(IniFile) do
  221.       try
  222.          Sections := TStringList.Create;
  223.          try
  224.             ReadSections(Sections);
  225.             Strings.BeginUpdate;
  226.             try
  227.                Strings.Clear;
  228.                for i := 0 to Sections.Count-1 do
  229.                begin
  230.                   P := Pos('.',Sections[i]);
  231.                   if (P <> 0) then Strings.Add(Copy(Sections[i],P+1,MaxInt));
  232.                end;
  233.             finally
  234.                Strings.EndUpdate;
  235.             end;
  236.          finally
  237.             Sections.Free;
  238.          end;
  239.       finally
  240.          Free;
  241.       end;
  242.    end;
  243. end;
  244. {-- TMMFlanger ------------------------------------------------------------}
  245. procedure TMMFlanger.DeleteSection(IniFile: TFileName; Section: string);
  246. begin
  247.    if (IniFile <> '') then
  248.    begin
  249.       with TIniFile.Create(IniFile) do
  250.       try
  251.          if Pos('Flanger.',Section) = 0 then Section := 'Flanger.'+Section;
  252.          EraseSection(Section);
  253.       finally
  254.          Free;
  255.       end;
  256.    end;
  257. end;
  258. {-- TMMFlanger ------------------------------------------------------------}
  259. procedure TMMFlanger.SetEnabled(aValue: Boolean);
  260. begin
  261.    if (aValue <> FEnabled) then
  262.    begin
  263.       FEnabled := aValue;
  264.       if FEnabled then Update;
  265.    end;
  266. end;
  267. {-- TMMFlanger ------------------------------------------------------------}
  268. procedure TMMFlanger.SetDescription(aValue: String);
  269. begin
  270.    if (aValue <> FDescription) then
  271.    begin
  272.       FDescription := aValue;
  273.       Change;
  274.    end;
  275. end;
  276. {-- TMMFlanger ------------------------------------------------------------}
  277. procedure TMMFlanger.SetGains(index: integer; aValue: TMMEffectVolume);
  278. begin
  279.    case index of
  280.        0: if (aValue = FDryMix) then exit
  281.           else
  282.           begin
  283.              FDryMix := aValue;
  284.              if FOpen then FPFlange^.DryMix := MulDiv(aValue,256,100);
  285.              Change;
  286.           end;
  287.        1: if (aValue = FWetMix) then exit
  288.           else
  289.           begin
  290.              FWetMix := aValue;
  291.              if FOpen then FPFlange^.Wetmix := MulDiv(aValue,256,100);
  292.              Change;
  293.           end;
  294.    end;
  295. end;
  296. {-- TMMFlanger ------------------------------------------------------------}
  297. procedure TMMFlanger.SetFeedBack(aValue: TMMFeedBack);
  298. begin
  299.    if (aValue <> FFeedBack) then
  300.    begin
  301.       FFeedBack := aValue;
  302.       if FOpen then FPFlange^.FeedBack := MulDiv(aValue,256,100);
  303.       Change;
  304.    end;
  305. end;
  306. {-- TMMFlanger ------------------------------------------------------------}
  307. procedure TMMFlanger.SetDelays(index: integer; aValue: integer);
  308. begin
  309.    case index of
  310.       0: if (aValue = FMaxDelay) then exit else
  311.          begin
  312.             FMaxDelay := Max(aValue,1);
  313.          end;
  314.       1: if (aValue = FDelay) then exit else
  315.          begin
  316.             FDelay := MinMax(aValue,1,FMaxDelay);
  317.             Update;
  318.             Change;
  319.          end;
  320.    end;
  321. end;
  322. {-- TMMFlanger ------------------------------------------------------------}
  323. procedure TMMFlanger.SetDepth(aValue: Float);
  324. begin
  325.    if (aValue <> FDepth) then
  326.    begin
  327.       FDepth := MaxR(aValue,0.0);
  328.       Update;
  329.       Change;
  330.    end;
  331. end;
  332. {-- TMMFlanger ------------------------------------------------------------}
  333. procedure TMMFlanger.SetRate(aValue: Float);
  334. begin
  335.    if (aValue <> FRate) then
  336.    begin
  337.       FRate := MaxR(aValue,0.0);
  338.       Update;
  339.       Change;
  340.    end;
  341. end;
  342. {-- TMMFlanger ------------------------------------------------------------}
  343. procedure TMMFlanger.Update;
  344. begin
  345.    { setup the phaser with the params }
  346.    if FOpen then
  347.    begin
  348.       FCleanup := 0;
  349.       if (FDelay > FCleanUp) then FCleanUp := FDelay;
  350.       if (FCleanup > 0) then
  351.       begin
  352.          { convert cleanup time to bytes }
  353.          FCleanup := wioTimeToSamples(PWaveFormat,FCleanup);
  354.       end;
  355.       SetFlanger(FPFlange, FDryMix, FWetMix, FFeedBack, FDelay, FDepth, FRate);
  356.    end;
  357. end;
  358. {-- TMMFlanger ------------------------------------------------------------}
  359. procedure TMMFlanger.SetPWaveFormat(aValue: PWaveFormatEx);
  360. begin
  361.    if (aValue <> nil) then
  362.    begin
  363.       if not (csDesigning in ComponentState) then
  364.          if not pcmIsValidFormat(aValue) then
  365.             raise EMMFlangeError.Create(LoadResStr(IDS_INVALIDFORMAT));
  366.    end;
  367.    inherited SetPWaveFormat(aValue);
  368. end;
  369. {-- TMMFlanger ------------------------------------------------------------}
  370. procedure TMMFlanger.Open;
  371. begin
  372.    if not FOpen then
  373.    begin
  374.       if pcmIsValidFormat(PWaveFormat) then
  375.       begin
  376.          FPFlange := InitFlanger(PWaveFormat,FMaxDelay);
  377.          if (FPFlange = nil) then OutOfMemoryError
  378.          else
  379.          begin
  380.             FOpen := True;
  381.             Update;
  382.          end;
  383.       end;
  384.    end;
  385. end;
  386. {-- TMMFlanger ------------------------------------------------------------}
  387. procedure TMMFlanger.Close;
  388. begin
  389.    if FOpen then
  390.    begin
  391.       FOpen := False;
  392.       DoneFlanger(FPFlange);
  393.    end;
  394. end;
  395. {-- TMMFlanger ------------------------------------------------------------}
  396. procedure TMMFlanger.Process(Buffer: PChar; Length: integer);
  397. begin
  398.    { process the buffer }
  399.    if (FPFlange <> nil) then
  400.       if DoFlanger(FPFlange, Buffer, Length) then
  401.          GlobalSynchronize(PcmOverflow);
  402. end;
  403. {-- TMMFlanger ------------------------------------------------------------}
  404. function TMMFlanger.CleanUp(Buffer: PChar; Length: integer): Longint;
  405. begin
  406.    { process the remaining delayed bytes in the delay lines }
  407.    if (FPFlange <> nil) and (FCleanup > 0) then
  408.    begin
  409.       FCleanup := Max(FCleanup - Length,0);
  410.       FillChar(Buffer^, Length, 0);
  411.       if DoFlanger(FPFlange, Buffer, Length) then
  412.          GlobalSynchronize(PcmOverflow);
  413.    end;
  414.    { return the remaining bytes to process }
  415.    Result := FCleanup;
  416. end;
  417. {-- TMMFlanger ------------------------------------------------------------}
  418. procedure TMMFlanger.Opened;
  419. begin
  420.    Open;
  421.    inherited Opened;
  422. end;
  423. {-- TMMFlanger ------------------------------------------------------------}
  424. procedure TMMFlanger.Closed;
  425. begin
  426.    Close;
  427.    inherited Closed;
  428. end;
  429. {-- TMMFlanger ------------------------------------------------------------}
  430. procedure TMMFlanger.Started;
  431. begin
  432.    Update;
  433.    inherited Started;
  434. end;
  435. {-- TMMFlanger ------------------------------------------------------------}
  436. procedure TMMFlanger.BufferReady(lpwh: PWaveHdr);
  437. begin
  438.    if Enabled and FOpen then
  439.    begin
  440.       Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
  441.    end;
  442.    inherited BufferReady(lpwh);
  443. end;
  444. {-- TMMFlanger ------------------------------------------------------------}
  445. procedure TMMFlanger.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  446. var
  447.    aLength: Longint;
  448. begin
  449.    inherited BufferLoad(lpwh, MoreBuffers);
  450.    if Enabled and FOpen then
  451.    begin
  452.       if not MoreBuffers then
  453.       begin
  454.          aLength := lpwh^.dwBufferLength;
  455.          if Cleanup(lpwh^.lpData, aLength) > 0 then MoreBuffers := True;
  456.          lpwh^.dwBytesRecorded := aLength;
  457.       end
  458.       else Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
  459.    end;
  460. end;
  461. end.