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

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/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: 09.09.98 - 12:05:18 $                                        =}
  24. {========================================================================}
  25. unit MMEQ;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     Messages,
  37.     Classes,
  38.     Controls,
  39.     Forms,
  40.     MMSystem,
  41.     MMRegs,
  42.     MMUtils,
  43.     MMPcmSup,
  44.     MMObj,
  45.     MMDSPObj,
  46.     MMObjLst,
  47.     MMFFT,
  48.     MMFFTFlt,
  49.     MMSpectr,
  50.     IniFiles,
  51.     Registry;
  52. const
  53.     {$IFDEF CBUILDER3} {$EXTERNALSYM defEnabled} {$ENDIF}
  54.     defEnabled = True;
  55.     {$IFDEF CBUILDER3} {$EXTERNALSYM defChannel} {$ENDIF}
  56.     defChannel = chBoth;
  57.     {$IFDEF CBUILDER3} {$EXTERNALSYM defFFTLen} {$ENDIF}
  58.     defFFTLen  = 256;
  59.     {$IFDEF CBUILDER3} {$EXTERNALSYM defRate} {$ENDIF}
  60.     defRate    = 4000;
  61.     {$IFDEF CBUILDER3} {$EXTERNALSYM defWindow} {$ENDIF}
  62.     defWindow  = fwHamming;
  63. type
  64.    EMMEqualizerError = class(Exception);
  65.    TMMEqualizer = class;
  66.    {-- TMMEQFilter ------------------------------------------------------------}
  67.    TMMEQFilter = class(TObject)
  68.    private
  69.       Ff1      : Float;
  70.       Ff2      : Float;
  71.       FGain    : Float;
  72.       FData    : Pointer;
  73.       FEnabled : Boolean;
  74.       FOnChange: TNotifyEvent;
  75.       procedure SetValue(index: integer; aValue: Float);
  76.       procedure SetEnabled(aValue: Boolean);
  77.       procedure Store(S: TStream); virtual;
  78.       procedure Load(S: TStream); virtual;
  79.    protected
  80.       procedure Changed; virtual;
  81.    public
  82.       constructor Create;
  83.       constructor CreateEx(af1,af2,aGain: Float);
  84.       constructor CreateObject(af1,af2,aGain: Float; Data: Pointer);
  85.       procedure Assign(Source: TObject);
  86.       procedure SetParams(af1, af2, aGain: Float);
  87.       property OnChange: TNotifyEvent read FOnChange write FOnChange;
  88.       property f1: Float index 0 read Ff1 write SetValue;
  89.       property f2: Float index 1 read Ff2 write SetValue;
  90.       property Gain: Float index 2 read FGain write SetValue;
  91.       property Data: Pointer read FData write FData;
  92.       property Enabled: Boolean read FEnabled write SetEnabled;
  93.    end;
  94.    {-- TMMEQFilterList --------------------------------------------------------}
  95.    TMMEQFilterList = class(TObjectList)
  96.    private
  97.       FEqualizer: TMMEqualizer;
  98.       procedure SetFilter(Index: integer; Filter: TMMEQFilter);
  99.       function  GetFilter(Index: integer): TMMEQFilter;
  100.    protected
  101.       procedure DefineProperties(Filer: TFiler); override;
  102.       procedure ReadData(S: TStream); override;
  103.       procedure WriteData(S: TStream); override;
  104.    public
  105.       function  AddObject(Item: TObject): TOLSize; override;
  106.       procedure Assign(Source: TPersistent); override;
  107.       property Items[Index: integer]: TMMEQFilter read GetFilter write SetFilter; default;
  108.    end;
  109.    {-- TMMEqualizer -----------------------------------------------------------}
  110.    TMMEqualizer = class(TMMDSPComponent)
  111.    private
  112.       FEnabled       : Boolean;
  113.       FOpen          : Boolean;
  114.       FPFilter       : PFFTFilter;
  115.       FPTempFilter   : PFFTFilter;
  116.       FDescription   : String;
  117.       FFTLen         : integer;
  118.       FFilters       : TMMEQFilterList;
  119.       FWindow        : TMMFFTWindow;
  120.       Ffs            : Longint;
  121.       FChannel       : TMMChannel;
  122.       FUpdating      : Boolean;
  123.       FRealBufSize   : Longint;
  124.       FSpectrum      : TMMSpectrum;
  125.       FOnChange      : TNotifyEvent;
  126.       FOnPcmOverflow : TNotifyEvent;
  127.       procedure SetFFTLen(aValue: integer);
  128.       procedure SetSampleRate(aValue: Longint);
  129.       procedure SetWindow(aValue: TMMFFTWindow);
  130.       procedure SetEnabled(aValue: Boolean);
  131.       procedure SetDescription(aValue: String);
  132.       procedure SetFilters(aValue: TMMEQFilterList);
  133.       procedure SetChannel(aValue: TMMChannel);
  134.       procedure SetSpectrum(aValue: TMMSpectrum);
  135.       procedure NotifySpectrum;
  136.       procedure SpectrumNeedData(Sender: TObject);
  137.       procedure FiltersChanged(Sender: TObject);
  138.       procedure FilterChanged(Sender: TObject);
  139.       procedure UpdateTempFilter(Init: Boolean);
  140.    protected
  141.       procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  142.       procedure Assign(Source: TPersistent); override;
  143.       procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  144.       procedure Loaded; override;
  145.       procedure Update; virtual;
  146.       procedure ResetEQ; virtual;
  147.       procedure Change; virtual;
  148.       procedure Opened; override;
  149.       procedure Closed; override;
  150.       procedure Started; override;
  151.       procedure Reseting; override;
  152.       procedure PcmOverflow; dynamic;
  153.       procedure BufferReady(lpwh: PWaveHdr); override;
  154.       procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  155.    public
  156.       constructor Create(aOwner: TComponent); override;
  157.       destructor  Destroy; override;
  158.       property IsOpen: Boolean read FOpen;
  159.       procedure Open;
  160.       procedure Reset;
  161.       procedure Close;
  162.       procedure Process(Buffer: PChar; Length: integer);
  163.       procedure SaveToRegIniFile(Ini: TRegIniFile; Section: string);
  164.       procedure ReadFromRegIniFile(Ini: TRegIniFile; Section: string);
  165.       procedure SaveToIniFileEx(Ini: TIniFile; Section: string);
  166.       procedure ReadFromIniFileEx(Ini: TIniFile; Section: string);
  167.       procedure SaveToIniFile(IniFile: TFileName; Section: string);
  168.       procedure ReadFromIniFile(IniFile: TFileName; Section: string);
  169.    published
  170.       property OnChange: TNotifyEvent read FOnChange write FOnChange;
  171.       property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
  172.       property Input;
  173.       property Output;
  174.       property Enabled: Boolean read FEnabled write SetEnabled default defEnabled;
  175.       property SampleRate: Longint read Ffs write SetSampleRate default defRate;
  176.       property FFTLength: integer read FFTLen write SetFFTLen default defFFTLen;
  177.       property Description: String read FDescription write SetDescription stored False;
  178.       property Filters: TMMEQFilterList read FFilters write SetFilters;
  179.       property Spectrum: TMMSpectrum read FSpectrum write SetSpectrum;
  180.       property Channel: TMMChannel read FChannel write SetChannel default defChannel;
  181.       property Window: TMMFFTWindow read FWindow write SetWindow default defWindow;
  182.    end;
  183. implementation
  184. const
  185.    STREAMKENNUNG : Longint = $00555145; { 'EQU ' }
  186. {== TMMEQFilter ===============================================================}
  187. constructor TMMEQFilter.Create;
  188. begin
  189.    inherited Create;
  190.    Ff1      := 0;
  191.    Ff2      := 0;
  192.    FGain    := 0;
  193.    FData    := nil;
  194.    FEnabled := True;
  195.    FOnChange:= nil;
  196. end;
  197. {-- TMMEQFilter ---------------------------------------------------------------}
  198. constructor TMMEQFilter.CreateEx(af1,af2,aGain: Float);
  199. begin
  200.    inherited Create;
  201.    Ff1      := af1;
  202.    Ff2      := af2;
  203.    FGain    := aGain;
  204.    FEnabled := True;
  205.    FOnChange:= nil;
  206. end;
  207. {-- TMMEQFilter ---------------------------------------------------------------}
  208. constructor TMMEQFilter.CreateObject(af1,af2,aGain: Float; Data: Pointer);
  209. begin
  210.    CreateEx(af1,af2,aGain);
  211.    FData := Data;
  212. end;
  213. {-- TMMEQFilter ---------------------------------------------------------------}
  214. procedure TMMEQFilter.Changed;
  215. begin
  216.    if assigned(FOnChange) then FOnChange(Self);
  217. end;
  218. {-- TMMEQFilter ---------------------------------------------------------------}
  219. procedure TMMEQFilter.SetParams(af1, af2, aGain: Float);
  220. begin
  221.    if (af1 <> Ff1) or (af2 <> Ff2) or (aGain <> FGain) then
  222.    begin
  223.       Ff1 := af1;
  224.       Ff2 := af2;
  225.       FGain := aGain;
  226.       Changed;
  227.    end;
  228. end;
  229. {-- TMMEQFilter ---------------------------------------------------------------}
  230. procedure TMMEQFilter.SetEnabled(aValue: Boolean);
  231. begin
  232.    if (aValue <> FEnabled) then
  233.    begin
  234.       FEnabled := aValue;
  235.       Changed;
  236.    end;
  237. end;
  238. {-- TMMEQFilter ---------------------------------------------------------------}
  239. procedure TMMEQFilter.SetValue(index: integer; aValue: Float);
  240. var
  241.    af1,af2,aGain: Float;
  242. begin
  243.    af1 := Ff1;
  244.    af2 := Ff2;
  245.    aGain := FGain;
  246.    case index of
  247.        0: af1 := aValue;
  248.        1: af2 := aValue;
  249.        2: aGain := aValue;
  250.    end;
  251.    SetParams(af1, af2, aGain);
  252. end;
  253. {-- TMMEQFilter ---------------------------------------------------------------}
  254. procedure TMMEQFilter.Store(S: TStream);
  255. begin
  256.    S.WriteBuffer(FEnabled,SizeOf(FEnabled));
  257.    S.WriteBuffer(Ff1,SizeOf(Ff1));
  258.    S.WriteBuffer(Ff2,SizeOf(Ff2));
  259.    S.WriteBuffer(FGain,SizeOf(FGain));
  260. end;
  261. {-- TMMEQFilter ---------------------------------------------------------------}
  262. procedure TMMEQFilter.Load(S: TStream);
  263. var
  264.    af1,af2,aGain: Float;
  265. begin
  266.    S.ReadBuffer(FEnabled,SizeOf(FEnabled));
  267.    S.ReadBuffer(af1,SizeOf(af1));
  268.    S.ReadBuffer(af2,SizeOf(af2));
  269.    S.ReadBuffer(aGain,SizeOf(aGain));
  270.    SetParams(af1,af2,aGain);
  271. end;
  272. {-- TMMEQFilter ---------------------------------------------------------------}
  273. procedure TMMEQFilter.Assign(Source: TObject);
  274. begin
  275.    if Source is TMMEQFilter then
  276.    begin
  277.       SetParams(TMMEQFilter(Source).f1,
  278.                 TMMEQFilter(Source).f2,
  279.                 TMMEQFilter(Source).Gain);
  280.       Data := TMMEQFilter(Source).Data;
  281.       Enabled := TMMEQFilter(Source).Enabled;
  282.    end;
  283. end;
  284. {== TMMEQFilterList ===========================================================}
  285. procedure TMMEQFilterList.SetFilter(Index: integer; Filter: TMMEQFilter);
  286. begin
  287.    Put(Index, Filter);
  288. end;
  289. {-- TMMEQFilterList -----------------------------------------------------------}
  290. function TMMEQFilterList.GetFilter(Index: integer): TMMEQFilter;
  291. begin
  292.    Result := TMMEQFilter(Get(Index));
  293. end;
  294. {-- TMMEQFilterList -----------------------------------------------------------}
  295. function TMMEQFilterList.AddObject(Item: TObject): TOLSize;
  296. begin
  297.    Result := inherited AddObject(Item);
  298.    (Item as TMMEQFilter).OnChange := FEqualizer.FilterChanged;
  299. end;
  300. {-- TMMEQFilterList -----------------------------------------------------------}
  301. procedure TMMEQFilterList.Assign(Source: TPersistent);
  302. var
  303.    i: integer;
  304.    Filter: TMMEQFilter;
  305. begin
  306.    if (Source is TMMEQFilterList) or (Source = nil) then
  307.    begin
  308.       BeginUpdate;
  309.       try
  310.          if (FEqualizer <> nil) then
  311.              FEqualizer.FUpdating := True;
  312.          FreeAll;
  313.          if (Source <> nil) then
  314.          for i := 0 to TMMEQFilterList(Source).Count-1 do
  315.          begin
  316.             Filter := TMMEQFilter.Create;
  317.             Filter.Assign(TMMEQFilterList(Source)[i]);
  318.             AddObject(Filter);
  319.          end;
  320.       finally
  321.          if (FEqualizer <> nil) then
  322.              FEqualizer.FUpdating := False;
  323.          EndUpdate;
  324.       end;
  325.    end
  326.    else inherited assign(Source);
  327. end;
  328. {-- TMMEQFilterList -----------------------------------------------------------}
  329. procedure TMMEQFilterList.DefineProperties(Filer: TFiler);
  330. begin
  331.    Filer.DefineBinaryProperty('ObjectContainer', ReadData, WriteData, True);
  332. end;
  333. {-- TMMEQFilterList -----------------------------------------------------------}
  334. procedure TMMEQFilterList.ReadData(S: TStream);
  335. Var
  336.    pBuf: PChar;
  337.    Kennung: Longint;
  338.    ObjCount,
  339.    Index: TOLSize;
  340.    Destroy: Boolean;
  341.    Value: Longint;
  342. begin
  343.    BeginUpdate;
  344.    try
  345.       FEqualizer.FUpdating := True;
  346.       S.ReadBuffer(Kennung,sizeOf(STREAMKENNUNG));
  347.       if (Kennung <> STREAMKENNUNG) then
  348.          raise EStreamError.Create('Invalid Object stream');
  349.       FreeAll;
  350.       { load stream items }
  351.       S.ReadBuffer(Destroy,SizeOf(Destroy));
  352.       DestroyObjects := Destroy;
  353.       { read string length }
  354.       S.ReadBuffer(Value,SizeOf(Value));
  355.       if Value > 0 then
  356.       begin
  357.          pBuf := StrAlloc(Value+1);
  358.          try
  359.             FillChar(pBuf^, Value+1, 0);
  360.             S.ReadBuffer(pBuf^, Value);
  361.             FEqualizer.Description := StrPas(pBuf);
  362.          finally
  363.             StrDispose(pBuf);
  364.          end;
  365.       end;
  366.       S.ReadBuffer(Value,SizeOf(Value));
  367.       FEqualizer.FFTLength := Value;
  368.       S.ReadBuffer(ObjCount,SizeOf(Objcount));  { Read in Object count }
  369.       if Capacity-Count < ObjCount then Capacity := Count+ObjCount;
  370.       { Read in Object Count }
  371.       for Index := 0 to ObjCount-1 do
  372.           AddObject(ReadObjectFromStream(S));
  373.    finally
  374.       FEqualizer.FUpdating := False;
  375.       EndUpdate;
  376.    end;
  377. end;
  378. {-- TMMEQFilterList -----------------------------------------------------------}
  379. procedure TMMEQFilterList.WriteData(S: TStream);
  380. var
  381.    Index,ObjCount: TOlSize;
  382.    Destroy: Boolean;
  383.    Value: Longint;
  384. begin
  385.    { Write list to Stream }
  386.    S.WriteBuffer(STREAMKENNUNG,SizeOf(STREAMKENNUNG));
  387.    Destroy := DestroyObjects;
  388.    S.WriteBuffer(Destroy,SizeOf(Destroy));
  389.    { write string length }
  390.    Value := Length(FEqualizer.FDescription);
  391.    S.WriteBuffer(Value, SizeOf(Value));
  392. {$IFDEF WIN32}
  393.    S.WriteBuffer(PChar(FEqualizer.FDescription)^, Length(FEqualizer.FDescription));
  394. {$ELSE}
  395.    S.WriteBuffer(FEqualizer.FDescription[1], Length(FEqaulizer.FDescription));
  396. {$ENDIF}
  397.    Value := FEqualizer.FFTLen;
  398.    S.WriteBuffer(Value, SizeOf(Value));
  399.    ObjCount := Count;
  400.    S.WriteBuffer(ObjCount,SizeOf(ObjCount));
  401.    for Index := 0 to Count-1 do
  402.        WriteObjectToStream(Items[Index],S);
  403. end;
  404. {== TMMEqualizer ==============================================================}
  405. constructor TMMEqualizer.Create(aOwner: TComponent);
  406. begin
  407.    inherited Create(aOwner);
  408.    FFilters := TMMEQFilterList.Create;
  409.    FFilters.OnChange := FiltersChanged;
  410.    FFilters.FEqualizer := Self;
  411.    FPFilter    := nil;
  412.    FPTempFilter:= nil;
  413.    FDescription:= 'Untitled';
  414.    Ffs         := defRate;
  415.    FWindow     := defWindow;
  416.    FChannel    := defChannel;
  417.    FEnabled    := defEnabled;
  418.    FOpen       := False;
  419.    FUpdating   := False;
  420.    FSpectrum   := nil;
  421.    FFTLen      := 8;
  422.    FFTLength   := defFFTLen;
  423.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  424.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  425. end;
  426. {-- TMMEqualizer --------------------------------------------------------------}
  427. destructor TMMEqualizer.Destroy;
  428. begin
  429.    Close;
  430.    SetSpectrum(nil);
  431.    FFilters.Free;
  432.    inherited Destroy;
  433. end;
  434. {-- TMMEqualizer --------------------------------------------------------------}
  435. procedure TMMEqualizer.Notification(aComponent: TComponent; Operation: TOperation);
  436. begin
  437.    inherited Notification(aComponent, Operation);
  438.    if (Operation = opRemove) then
  439.    begin
  440.       if (aComponent = FSpectrum) then
  441.           FSpectrum := nil;
  442.    end;
  443. end;
  444. {-- TMMEqualizer --------------------------------------------------------------}
  445. procedure TMMEqualizer.PcmOverflow;
  446. begin
  447.    if assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
  448. end;
  449. {-- TMMEqualizer --------------------------------------------------------------}
  450. procedure TMMEqualizer.SetPWaveFormat(aValue: PWaveFormatEx);
  451. begin
  452.    if (aValue <> nil) then
  453.    begin
  454.       if not (csDesigning in ComponentState) then
  455.          if not pcmIsValidFormat(aValue) or (aValue^.wBitsPerSample = 8) then
  456.             raise EMMEqualizerError.Create(LoadResStr(IDS_INVALIDFORMAT));
  457.       SampleRate := aValue^.nSamplesPerSec;
  458.    end;
  459.    inherited SetPWaveFormat(aValue);
  460. end;
  461. {-- TMMEqualizer --------------------------------------------------------------}
  462. procedure TMMEqualizer.SaveToRegIniFile(Ini: TRegIniFile; Section: string);
  463. var
  464.    i: integer;
  465. begin
  466.    if (Ini <> nil) then
  467.    begin
  468.       with Ini do
  469.       begin
  470.          WriteInteger(Section, 'FFTLen', FFTLength);
  471.          WriteInteger(Section, 'Samplerate', Samplerate);
  472.          WriteInteger(Section, 'Window', Ord(Window));
  473.          WriteInteger(Section, 'Bands', Filters.Count);
  474.          for i := 0 to Filters.Count-1 do
  475.          with Filters[i] do
  476.          begin
  477.             WriteString(Section, 'Band'+IntToStr(i)+' f1', FloatToStr(f1));
  478.             WriteString(Section, 'Band'+IntToStr(i)+' f2', FloatToStr(f2));
  479.             WriteString(Section, 'Band'+IntToStr(i)+' Gain', FloatToStr(Gain));
  480.             WriteBool(Section, 'Band'+IntToStr(i)+' Enabled', Enabled);
  481.          end;
  482.       end;
  483.    end;
  484. end;
  485. {-- TMMEqualizer --------------------------------------------------------------}
  486. procedure TMMEqualizer.SaveToIniFileEx(Ini: TIniFile; Section: string);
  487. var
  488.    i: integer;
  489. begin
  490.    if (Ini <> nil) then
  491.    begin
  492.       with Ini do
  493.       begin
  494.          WriteInteger(Section, 'FFTLen', FFTLength);
  495.          WriteInteger(Section, 'Samplerate', Samplerate);
  496.          WriteInteger(Section, 'Window', Ord(Window));
  497.          WriteInteger(Section, 'Bands', Filters.Count);
  498.          for i := 0 to Filters.Count-1 do
  499.          with Filters[i] do
  500.          begin
  501.             WriteString(Section, 'Band'+IntToStr(i)+' f1', FloatToStr(f1));
  502.             WriteString(Section, 'Band'+IntToStr(i)+' f2', FloatToStr(f2));
  503.             WriteString(Section, 'Band'+IntToStr(i)+' Gain', FloatToStr(Gain));
  504.             WriteBool(Section, 'Band'+IntToStr(i)+' Enabled', Enabled);
  505.          end;
  506.       end;
  507.    end;
  508. end;
  509. {-- TMMEqualizer --------------------------------------------------------------}
  510. procedure TMMEqualizer.ReadFromRegIniFile(Ini: TRegIniFile; Section: string);
  511. var
  512.    Cnt, i: integer;
  513.    f1,f2,Gain: Float;
  514.    Enabl: Boolean;
  515. begin
  516.    if (Ini <> nil) then
  517.    begin
  518.       with Ini do
  519.       begin
  520.          i := ReadInteger(Section, 'FFTLen', -1);
  521.          if (i > 0) then
  522.          begin
  523.             Filters.BeginUpdate;
  524.             try
  525.                FUpdating := True;
  526.                Filters.FreeAll;
  527.                FFTLength   := ReadInteger(Section, 'FFTLen', defFFTLen);
  528.                Samplerate  := ReadInteger(Section, 'Samplerate', defRate);
  529.                Window      := TMMFFTWindow(ReadInteger(Section, 'Window', Ord(defWindow)));
  530.                Description := Section;
  531.                Cnt := ReadInteger(Section, 'Bands', 0);
  532.                for i := 0 to Cnt-1 do
  533.                begin
  534.                   f1   := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f1', '0')));
  535.                   f2   := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f2', '0')));
  536.                   Gain := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' Gain', '0')));
  537.                   Enabl:= ReadBool(Section, 'Band'+IntToStr(i)+' Enabled', True);
  538.                   Filters.AddObject(TMMEQFilter.CreateEx(f1,f2,Gain));
  539.                   Filters[i].Enabled := Enabl;
  540.                end;
  541.             finally
  542.                FUpdating := False;
  543.                Filters.EndUpdate;
  544.             end;
  545.          end;
  546.       end;
  547.    end;
  548. end;
  549. {-- TMMEqualizer --------------------------------------------------------------}
  550. procedure TMMEqualizer.ReadFromIniFileEx(Ini: TIniFile; Section: string);
  551. var
  552.    Cnt, i: integer;
  553.    f1,f2,Gain: Float;
  554.    Enabl: Boolean;
  555. begin
  556.    if (Ini <> nil) then
  557.    begin
  558.       with Ini do
  559.       begin
  560.          i := ReadInteger(Section, 'FFTLen', -1);
  561.          if (i > 0) then
  562.          begin
  563.             Filters.BeginUpdate;
  564.             try
  565.                FUpdating := True;
  566.                Filters.FreeAll;
  567.                FFTLength   := ReadInteger(Section, 'FFTLen', defFFTLen);
  568.                Samplerate  := ReadInteger(Section, 'Samplerate', defRate);
  569.                Window      := TMMFFTWindow(ReadInteger(Section, 'Window', Ord(defWindow)));
  570.                Description := Section;
  571.                Cnt := ReadInteger(Section, 'Bands', 0);
  572.                for i := 0 to Cnt-1 do
  573.                begin
  574.                   f1   := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f1', '0')));
  575.                   f2   := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f2', '0')));
  576.                   Gain := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' Gain', '0')));
  577.                   Enabl:= ReadBool(Section, 'Band'+IntToStr(i)+' Enabled', True);
  578.                   Filters.AddObject(TMMEQFilter.CreateEx(f1,f2,Gain));
  579.                   Filters[i].Enabled := Enabl;
  580.                end;
  581.             finally
  582.                FUpdating := False;
  583.                Filters.EndUpdate;
  584.             end;
  585.          end;
  586.       end;
  587.    end;
  588. end;
  589. {-- TMMEqualizer --------------------------------------------------------------}
  590. procedure TMMEqualizer.SaveToIniFile(IniFile: TFileName; Section: string);
  591. var
  592.    Ini: TIniFile;
  593. begin
  594.    if (IniFile <> '') then
  595.    begin
  596.       Ini := TIniFile.Create(IniFile);
  597.       try
  598.          Section := 'EQ.'+Section;
  599.          SaveToIniFileEx(Ini, Section);
  600.       finally
  601.          Ini.Free;
  602.       end;
  603.    end;
  604. end;
  605. {-- TMMEqualizer --------------------------------------------------------------}
  606. procedure TMMEqualizer.ReadFromIniFile(IniFile: TFileName; Section: string);
  607. var
  608.    Ini: TInifile;
  609. begin
  610.    if (IniFile <> '') then
  611.    begin
  612.       Ini := TIniFile.Create(IniFile);
  613.       try
  614.          Section := 'EQ.'+Section;
  615.          ReadFromIniFileEx(Ini,Section);
  616.       finally
  617.          Ini.Free;
  618.       end;
  619.    end;
  620. end;
  621. {-- TMMEqualizer --------------------------------------------------------------}
  622. procedure TMMEqualizer.SetFilters(aValue: TMMEQFilterList);
  623. begin
  624.    if (aValue <> FFilters) then FFilters.Assign(aValue);
  625. end;
  626. {-- TMMEqualizer --------------------------------------------------------------}
  627. procedure TMMEqualizer.FilterChanged(Sender: TObject);
  628. begin
  629.    { setup one equalizer band with the params }
  630.    if not FUpdating then
  631.    begin
  632.       if FOpen then
  633.       with (Sender as TMMEQFilter) do
  634.       begin
  635.          { now update the filter channels }
  636.          if Enabled then
  637.             SetFFTFilterBand(FPFilter,f1,f2,gain)
  638.          else
  639.             SetFFTFilterBand(FPFilter,f1,f2,0);
  640.       end;
  641.       Change;
  642.    end;
  643. end;
  644. {-- TMMEqualizer --------------------------------------------------------------}
  645. procedure TMMEqualizer.FiltersChanged(Sender: TObject);
  646. begin
  647.    if not FUpdating and (Filters.UpdateCount = 0) then
  648.    begin
  649.       Update;
  650.       Change;
  651.    end;
  652. end;
  653. {-- TMMEqualizer --------------------------------------------------------------}
  654. procedure TMMEqualizer.Loaded;
  655. begin
  656.    inherited Loaded;
  657.    NotifySpectrum;
  658. end;
  659. {-- TMMEqualizer --------------------------------------------------------------}
  660. procedure TMMEqualizer.Change;
  661. begin
  662.    NotifySpectrum;
  663.    if assigned(FOnChange) then FOnChange(Self);
  664. end;
  665. {-- TMMEqualizer --------------------------------------------------------------}
  666. procedure TMMEqualizer.Update;
  667. var
  668.    i: integer;
  669. begin
  670.    { setup the equalizer with the params }
  671.    if FOpen then
  672.    begin
  673.       ResetEQ;
  674.       for i := 0 to Filters.Count-1 do
  675.       with Filters[i] do
  676.       begin
  677.         { now update the filter channels }
  678.         if Enabled then SetFFTFilterBand(FPFilter,f1,f2,Gain);
  679.       end;
  680.    end;
  681. end;
  682. {-- TMMEqualizer --------------------------------------------------------------}
  683. procedure TMMEqualizer.ResetEQ;
  684. begin
  685.    if FOpen and (FPFilter <> nil) then
  686.    begin
  687.       { reset the equalizer }
  688.       SetFFTFilterBand(FPFilter,0,Ffs/2,0);
  689.    end;
  690. end;
  691. {-- TMMEqualizer --------------------------------------------------------------}
  692. procedure TMMEqualizer.UpdateTempFilter(Init: Boolean);
  693. var
  694.    wfx: TWaveFormatEx;
  695. begin
  696.    DoneFFTFilter(FPTempFilter);
  697.    if Init and (FSpectrum <> nil) then
  698.    begin
  699.       pcmBuildWaveHeader(@wfx, 16, 1, Ffs);
  700.       FPTempFilter := InitFFTFilter(@wfx,FFTLen,8192);
  701.       FSpectrum.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  702.       SetFFTFilterWindow(FPTempFilter,Ord(FWindow));
  703.       NotifySpectrum;
  704.    end;
  705. end;
  706. {-- TMMEqualizer --------------------------------------------------------------}
  707. procedure TMMEqualizer.SetSpectrum(aValue: TMMSpectrum);
  708. begin
  709.    if Longint(Self) = Longint(aValue) then exit;
  710.    if (aValue <> FSpectrum) then
  711.    begin
  712.       if (aValue = nil) then
  713.       begin
  714.          FSpectrum.OnNeedData := nil;
  715.          NotifySpectrum;
  716.          UpdateTempFilter(False);
  717.       end;
  718.       FSpectrum := aValue;
  719.       if (FSpectrum <> nil) then
  720.       begin
  721.          UpdateTempFilter(True);
  722.          FSpectrum.Window := fwRectangular;
  723.          FSpectrum.OnNeedData := SpectrumNeedData;
  724.          NotifySpectrum;
  725.       end;
  726.    end;
  727. end;
  728. {-- TMMEqualizer --------------------------------------------------------------}
  729. procedure TMMEqualizer.NotifySpectrum;
  730. begin
  731.    if (FSpectrum = nil) or
  732.       (csLoading in ComponentState) or
  733.       (csReading in ComponentState) then exit;
  734.    FSpectrum.ResetData;
  735. end;
  736. {-- TMMEqualizer --------------------------------------------------------------}
  737. procedure TMMEqualizer.SpectrumNeedData(Sender: TObject);
  738. var
  739.    i: integer;
  740.    Buf: array[0..8192] of Smallint;
  741. begin
  742.    if (Sender <> nil) and (FPTempFilter <> nil) then
  743.    with TMMSpectrum(Sender) do
  744.    begin
  745.       { reset the filter }
  746.       SetFFTFilterBand(FPTempFilter,0,Ffs/2, 0);
  747.       for i := 0 to Filters.Count-1 do
  748.       with Filters[i] do
  749.       begin
  750.          { now update the filter bands }
  751.          if Enabled then SetFFTFilterBand(FPTempFilter,f1,f2,Gain);
  752.       end;
  753.       GlobalFillMem(Buf,sizeOf(Buf),0);
  754.       Buf[0] := 21500;
  755.       DoFFTFilter(FPTempFilter, chLeft, @Buf, Max(BytesPerSpectrum,2*FFTLen));
  756.       RefreshPCMData(@Buf);
  757.    end;
  758. end;
  759. {-- TMMEqualizer --------------------------------------------------------------}
  760. procedure TMMEqualizer.Assign(Source: TPersistent);
  761. begin
  762.    if (Source is TMMEqualizer) then
  763.    begin
  764.       if (Source <> nil) then
  765.       begin
  766.          Channel    := TMMEqualizer(Source).Channel;
  767.          Enabled    := TMMEqualizer(Source).Enabled;
  768.          Description:= TMMEqualizer(Source).Description;
  769.          FFTLength  := TMMEqualizer(Source).FFTLength;
  770.          Window     := TMMEqualizer(Source).Window;
  771.          Filters    := TMMEqualizer(Source).Filters;
  772.          SampleRate := TMMEqualizer(Source).SampleRate;
  773.       end;
  774.    end;
  775. end;
  776. {-- TMMEqualizer --------------------------------------------------------------}
  777. procedure TMMEqualizer.SetChannel(aValue: TMMChannel);
  778. begin
  779.    if (aValue <> FChannel) then
  780.    begin
  781.       FChannel := aValue;
  782.    end;
  783. end;
  784. {-- TMMEqualizer --------------------------------------------------------------}
  785. procedure TMMEqualizer.SetSampleRate(aValue: Longint);
  786. begin
  787.    if (aValue <> Ffs) then
  788.    begin
  789.       Ffs := MinMax(aValue,4000,100000);
  790.       UpdateTempFilter(True);
  791.    end;
  792. end;
  793. {-- TMMEqualizer --------------------------------------------------------------}
  794. procedure TMMEqualizer.SetWindow(aValue: TMMFFTWindow);
  795. begin
  796.    if (aValue <> FWindow) then
  797.    begin
  798.       FWindow := aValue;
  799.       if FOpen then SetFFTFilterWindow(FPFilter,Ord(FWindow));
  800.       UpdateTempFilter(True);
  801.    end;
  802. end;
  803. {-- TMMEqualizer --------------------------------------------------------------}
  804. procedure TMMEqualizer.SetFFTLen(aValue: integer);
  805. var
  806.    Order: integer;
  807. begin
  808. { band wide = (44100/2)/(FFTLen/2) = 172 Hz. for fft(256)         }
  809. {             (44100/2)/(FFTLen/2) = 86 Hz wide of band. fft(512) }
  810.    aValue := MinMax(aValue,8,MAX_FFTLEN);
  811.    { Convert FFTLen to a power of 2 }
  812.    Order := 0;
  813.    while aValue > 1 do
  814.    begin
  815.       aValue := aValue shr 1;
  816.       inc(Order);
  817.    end;
  818.    if (Order > 0) then aValue := aValue shl Order;
  819.    if (aValue <> FFTLen) then
  820.    begin
  821.       { re-init the FFTObject with the new FFT-length }
  822.       FFTLen := aValue;
  823.       UpdateTempFilter(True);
  824.       if FOpen then
  825.       begin
  826.          DoneFFTFilter(FPFilter);
  827.          FPFilter := InitFFTFilter(PWaveFormat, FFTLength, FRealBufSize);
  828.          if (FPFilter = nil) then OutOfMemoryError;
  829.          SetFFTFilterWindow(FPFilter,Ord(FWindow));
  830.          Update;
  831.       end;
  832.    end;
  833. end;
  834. {-- TMMEqualizer --------------------------------------------------------------}
  835. procedure TMMEqualizer.SetDescription(aValue: String);
  836. begin
  837.    if (aValue <> FDescription) then
  838.    begin
  839.       FDescription := aValue;
  840.    end;
  841. end;
  842. {-- TMMEqualizer --------------------------------------------------------------}
  843. procedure TMMEqualizer.SetEnabled(aValue: Boolean);
  844. begin
  845.    if (aValue <> FEnabled) then
  846.    begin
  847.       FEnabled := aValue;
  848.       Reset;
  849.    end;
  850. end;
  851. {-- TMMEqualizer --------------------------------------------------------------}
  852. procedure TMMEqualizer.Open;
  853. begin
  854.    if not FOpen then
  855.    begin
  856.       if pcmIsValidFormat(PWaveFormat) then
  857.       begin
  858.          FRealBufSize := Max(Max(QUEUE_READ_SIZE,QUEUE_WRITE_SIZE),BufferSize);
  859.          FPFilter := InitFFTFilter(PWaveFormat, FFTLength, FRealBufSize);
  860.          if (FPFilter = nil) then OutOfMemoryError;
  861.          SetFFTFilterWindow(FPFilter,Ord(FWindow));
  862.          FOpen := True;
  863.          Update;
  864.       end;
  865.    end;
  866. end;
  867. {-- TMMEqualizer --------------------------------------------------------------}
  868. procedure TMMEqualizer.Reset;
  869. begin
  870.    if FOpen and (FPFilter <> nil) then
  871.    begin
  872.       ResetFFTFilter(FPFilter);
  873.    end;
  874. end;
  875. {-- TMMEqualizer --------------------------------------------------------------}
  876. procedure TMMEqualizer.Close;
  877. begin
  878.    if FOpen then
  879.    begin
  880.       FOpen := False;
  881.       DoneFFTFilter(FPFilter);
  882.    end;
  883. end;
  884. {-- TMMEqualizer --------------------------------------------------------------}
  885. procedure TMMEqualizer.Process(Buffer: PChar; Length: integer);
  886. begin
  887.    { process the buffer trough the filter engine }
  888.    if FOpen and (FPFilter <> nil) and FEnabled then
  889.    begin
  890.       if DoFFTFilter(FPFilter, FChannel, Buffer, Length) then
  891.       begin
  892.          if assigned(FOnPcmOverflow) then
  893.             GlobalSynchronize(PcmOverflow);
  894.       end;
  895.    end;
  896. end;
  897. {-- TMMEqualizer --------------------------------------------------------------}
  898. procedure TMMEqualizer.Opened;
  899. begin
  900.    Open;
  901.    inherited Opened;
  902. end;
  903. {-- TMMEqualizer --------------------------------------------------------------}
  904. procedure TMMEqualizer.Closed;
  905. begin
  906.    Close;
  907.    inherited Closed;
  908. end;
  909. {-- TMMEqualizer --------------------------------------------------------------}
  910. procedure TMMEqualizer.Started;
  911. begin
  912.    Update;
  913.    Reset;
  914.    inherited Started;
  915. end;
  916. {-- TMMEqualizer --------------------------------------------------------------}
  917. procedure TMMEqualizer.Reseting;
  918. begin
  919.    Reset;
  920.    inherited Reseting;
  921. end;
  922. {-- TMMEqualizer --------------------------------------------------------------}
  923. procedure TMMEqualizer.BufferReady(lpwh: PWaveHdr);
  924. begin
  925.    if FOpen then
  926.    begin
  927.       Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
  928.    end;
  929.    inherited BufferReady(lpwh);
  930. end;
  931. {-- TMMEqualizer --------------------------------------------------------------}
  932. procedure TMMEqualizer.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  933. begin
  934.    inherited BufferLoad(lpwh, MoreBuffers);
  935.    if FOpen then
  936.    begin
  937.       Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
  938.    end;
  939. end;
  940. initialization
  941.    { register filter class for streaming ! }
  942.    DoRegisterClass(@TMMEQFilter.Load,
  943.                    @TMMEQFilter.Store,
  944.                     TMMEQFilter);
  945. end.