MMEQ.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:33k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49 (0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 09.09.98 - 12:05:18 $ =}
- {========================================================================}
- unit MMEQ;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- SysUtils,
- Messages,
- Classes,
- Controls,
- Forms,
- MMSystem,
- MMRegs,
- MMUtils,
- MMPcmSup,
- MMObj,
- MMDSPObj,
- MMObjLst,
- MMFFT,
- MMFFTFlt,
- MMSpectr,
- IniFiles,
- Registry;
- const
- {$IFDEF CBUILDER3} {$EXTERNALSYM defEnabled} {$ENDIF}
- defEnabled = True;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defChannel} {$ENDIF}
- defChannel = chBoth;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defFFTLen} {$ENDIF}
- defFFTLen = 256;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defRate} {$ENDIF}
- defRate = 4000;
- {$IFDEF CBUILDER3} {$EXTERNALSYM defWindow} {$ENDIF}
- defWindow = fwHamming;
- type
- EMMEqualizerError = class(Exception);
- TMMEqualizer = class;
- {-- TMMEQFilter ------------------------------------------------------------}
- TMMEQFilter = class(TObject)
- private
- Ff1 : Float;
- Ff2 : Float;
- FGain : Float;
- FData : Pointer;
- FEnabled : Boolean;
- FOnChange: TNotifyEvent;
- procedure SetValue(index: integer; aValue: Float);
- procedure SetEnabled(aValue: Boolean);
- procedure Store(S: TStream); virtual;
- procedure Load(S: TStream); virtual;
- protected
- procedure Changed; virtual;
- public
- constructor Create;
- constructor CreateEx(af1,af2,aGain: Float);
- constructor CreateObject(af1,af2,aGain: Float; Data: Pointer);
- procedure Assign(Source: TObject);
- procedure SetParams(af1, af2, aGain: Float);
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property f1: Float index 0 read Ff1 write SetValue;
- property f2: Float index 1 read Ff2 write SetValue;
- property Gain: Float index 2 read FGain write SetValue;
- property Data: Pointer read FData write FData;
- property Enabled: Boolean read FEnabled write SetEnabled;
- end;
- {-- TMMEQFilterList --------------------------------------------------------}
- TMMEQFilterList = class(TObjectList)
- private
- FEqualizer: TMMEqualizer;
- procedure SetFilter(Index: integer; Filter: TMMEQFilter);
- function GetFilter(Index: integer): TMMEQFilter;
- protected
- procedure DefineProperties(Filer: TFiler); override;
- procedure ReadData(S: TStream); override;
- procedure WriteData(S: TStream); override;
- public
- function AddObject(Item: TObject): TOLSize; override;
- procedure Assign(Source: TPersistent); override;
- property Items[Index: integer]: TMMEQFilter read GetFilter write SetFilter; default;
- end;
- {-- TMMEqualizer -----------------------------------------------------------}
- TMMEqualizer = class(TMMDSPComponent)
- private
- FEnabled : Boolean;
- FOpen : Boolean;
- FPFilter : PFFTFilter;
- FPTempFilter : PFFTFilter;
- FDescription : String;
- FFTLen : integer;
- FFilters : TMMEQFilterList;
- FWindow : TMMFFTWindow;
- Ffs : Longint;
- FChannel : TMMChannel;
- FUpdating : Boolean;
- FRealBufSize : Longint;
- FSpectrum : TMMSpectrum;
- FOnChange : TNotifyEvent;
- FOnPcmOverflow : TNotifyEvent;
- procedure SetFFTLen(aValue: integer);
- procedure SetSampleRate(aValue: Longint);
- procedure SetWindow(aValue: TMMFFTWindow);
- procedure SetEnabled(aValue: Boolean);
- procedure SetDescription(aValue: String);
- procedure SetFilters(aValue: TMMEQFilterList);
- procedure SetChannel(aValue: TMMChannel);
- procedure SetSpectrum(aValue: TMMSpectrum);
- procedure NotifySpectrum;
- procedure SpectrumNeedData(Sender: TObject);
- procedure FiltersChanged(Sender: TObject);
- procedure FilterChanged(Sender: TObject);
- procedure UpdateTempFilter(Init: Boolean);
- protected
- procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
- procedure Assign(Source: TPersistent); override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure Loaded; override;
- procedure Update; virtual;
- procedure ResetEQ; virtual;
- procedure Change; virtual;
- procedure Opened; override;
- procedure Closed; override;
- procedure Started; override;
- procedure Reseting; override;
- procedure PcmOverflow; dynamic;
- procedure BufferReady(lpwh: PWaveHdr); override;
- procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
- public
- constructor Create(aOwner: TComponent); override;
- destructor Destroy; override;
- property IsOpen: Boolean read FOpen;
- procedure Open;
- procedure Reset;
- procedure Close;
- procedure Process(Buffer: PChar; Length: integer);
- procedure SaveToRegIniFile(Ini: TRegIniFile; Section: string);
- procedure ReadFromRegIniFile(Ini: TRegIniFile; Section: string);
- procedure SaveToIniFileEx(Ini: TIniFile; Section: string);
- procedure ReadFromIniFileEx(Ini: TIniFile; Section: string);
- procedure SaveToIniFile(IniFile: TFileName; Section: string);
- procedure ReadFromIniFile(IniFile: TFileName; Section: string);
- published
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
- property Input;
- property Output;
- property Enabled: Boolean read FEnabled write SetEnabled default defEnabled;
- property SampleRate: Longint read Ffs write SetSampleRate default defRate;
- property FFTLength: integer read FFTLen write SetFFTLen default defFFTLen;
- property Description: String read FDescription write SetDescription stored False;
- property Filters: TMMEQFilterList read FFilters write SetFilters;
- property Spectrum: TMMSpectrum read FSpectrum write SetSpectrum;
- property Channel: TMMChannel read FChannel write SetChannel default defChannel;
- property Window: TMMFFTWindow read FWindow write SetWindow default defWindow;
- end;
- implementation
- const
- STREAMKENNUNG : Longint = $00555145; { 'EQU ' }
- {== TMMEQFilter ===============================================================}
- constructor TMMEQFilter.Create;
- begin
- inherited Create;
- Ff1 := 0;
- Ff2 := 0;
- FGain := 0;
- FData := nil;
- FEnabled := True;
- FOnChange:= nil;
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- constructor TMMEQFilter.CreateEx(af1,af2,aGain: Float);
- begin
- inherited Create;
- Ff1 := af1;
- Ff2 := af2;
- FGain := aGain;
- FEnabled := True;
- FOnChange:= nil;
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- constructor TMMEQFilter.CreateObject(af1,af2,aGain: Float; Data: Pointer);
- begin
- CreateEx(af1,af2,aGain);
- FData := Data;
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.Changed;
- begin
- if assigned(FOnChange) then FOnChange(Self);
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.SetParams(af1, af2, aGain: Float);
- begin
- if (af1 <> Ff1) or (af2 <> Ff2) or (aGain <> FGain) then
- begin
- Ff1 := af1;
- Ff2 := af2;
- FGain := aGain;
- Changed;
- end;
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.SetEnabled(aValue: Boolean);
- begin
- if (aValue <> FEnabled) then
- begin
- FEnabled := aValue;
- Changed;
- end;
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.SetValue(index: integer; aValue: Float);
- var
- af1,af2,aGain: Float;
- begin
- af1 := Ff1;
- af2 := Ff2;
- aGain := FGain;
- case index of
- 0: af1 := aValue;
- 1: af2 := aValue;
- 2: aGain := aValue;
- end;
- SetParams(af1, af2, aGain);
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.Store(S: TStream);
- begin
- S.WriteBuffer(FEnabled,SizeOf(FEnabled));
- S.WriteBuffer(Ff1,SizeOf(Ff1));
- S.WriteBuffer(Ff2,SizeOf(Ff2));
- S.WriteBuffer(FGain,SizeOf(FGain));
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.Load(S: TStream);
- var
- af1,af2,aGain: Float;
- begin
- S.ReadBuffer(FEnabled,SizeOf(FEnabled));
- S.ReadBuffer(af1,SizeOf(af1));
- S.ReadBuffer(af2,SizeOf(af2));
- S.ReadBuffer(aGain,SizeOf(aGain));
- SetParams(af1,af2,aGain);
- end;
- {-- TMMEQFilter ---------------------------------------------------------------}
- procedure TMMEQFilter.Assign(Source: TObject);
- begin
- if Source is TMMEQFilter then
- begin
- SetParams(TMMEQFilter(Source).f1,
- TMMEQFilter(Source).f2,
- TMMEQFilter(Source).Gain);
- Data := TMMEQFilter(Source).Data;
- Enabled := TMMEQFilter(Source).Enabled;
- end;
- end;
- {== TMMEQFilterList ===========================================================}
- procedure TMMEQFilterList.SetFilter(Index: integer; Filter: TMMEQFilter);
- begin
- Put(Index, Filter);
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- function TMMEQFilterList.GetFilter(Index: integer): TMMEQFilter;
- begin
- Result := TMMEQFilter(Get(Index));
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- function TMMEQFilterList.AddObject(Item: TObject): TOLSize;
- begin
- Result := inherited AddObject(Item);
- (Item as TMMEQFilter).OnChange := FEqualizer.FilterChanged;
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- procedure TMMEQFilterList.Assign(Source: TPersistent);
- var
- i: integer;
- Filter: TMMEQFilter;
- begin
- if (Source is TMMEQFilterList) or (Source = nil) then
- begin
- BeginUpdate;
- try
- if (FEqualizer <> nil) then
- FEqualizer.FUpdating := True;
- FreeAll;
- if (Source <> nil) then
- for i := 0 to TMMEQFilterList(Source).Count-1 do
- begin
- Filter := TMMEQFilter.Create;
- Filter.Assign(TMMEQFilterList(Source)[i]);
- AddObject(Filter);
- end;
- finally
- if (FEqualizer <> nil) then
- FEqualizer.FUpdating := False;
- EndUpdate;
- end;
- end
- else inherited assign(Source);
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- procedure TMMEQFilterList.DefineProperties(Filer: TFiler);
- begin
- Filer.DefineBinaryProperty('ObjectContainer', ReadData, WriteData, True);
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- procedure TMMEQFilterList.ReadData(S: TStream);
- Var
- pBuf: PChar;
- Kennung: Longint;
- ObjCount,
- Index: TOLSize;
- Destroy: Boolean;
- Value: Longint;
- begin
- BeginUpdate;
- try
- FEqualizer.FUpdating := True;
- S.ReadBuffer(Kennung,sizeOf(STREAMKENNUNG));
- if (Kennung <> STREAMKENNUNG) then
- raise EStreamError.Create('Invalid Object stream');
- FreeAll;
- { load stream items }
- S.ReadBuffer(Destroy,SizeOf(Destroy));
- DestroyObjects := Destroy;
- { read string length }
- S.ReadBuffer(Value,SizeOf(Value));
- if Value > 0 then
- begin
- pBuf := StrAlloc(Value+1);
- try
- FillChar(pBuf^, Value+1, 0);
- S.ReadBuffer(pBuf^, Value);
- FEqualizer.Description := StrPas(pBuf);
- finally
- StrDispose(pBuf);
- end;
- end;
- S.ReadBuffer(Value,SizeOf(Value));
- FEqualizer.FFTLength := Value;
- S.ReadBuffer(ObjCount,SizeOf(Objcount)); { Read in Object count }
- if Capacity-Count < ObjCount then Capacity := Count+ObjCount;
- { Read in Object Count }
- for Index := 0 to ObjCount-1 do
- AddObject(ReadObjectFromStream(S));
- finally
- FEqualizer.FUpdating := False;
- EndUpdate;
- end;
- end;
- {-- TMMEQFilterList -----------------------------------------------------------}
- procedure TMMEQFilterList.WriteData(S: TStream);
- var
- Index,ObjCount: TOlSize;
- Destroy: Boolean;
- Value: Longint;
- begin
- { Write list to Stream }
- S.WriteBuffer(STREAMKENNUNG,SizeOf(STREAMKENNUNG));
- Destroy := DestroyObjects;
- S.WriteBuffer(Destroy,SizeOf(Destroy));
- { write string length }
- Value := Length(FEqualizer.FDescription);
- S.WriteBuffer(Value, SizeOf(Value));
- {$IFDEF WIN32}
- S.WriteBuffer(PChar(FEqualizer.FDescription)^, Length(FEqualizer.FDescription));
- {$ELSE}
- S.WriteBuffer(FEqualizer.FDescription[1], Length(FEqaulizer.FDescription));
- {$ENDIF}
- Value := FEqualizer.FFTLen;
- S.WriteBuffer(Value, SizeOf(Value));
- ObjCount := Count;
- S.WriteBuffer(ObjCount,SizeOf(ObjCount));
- for Index := 0 to Count-1 do
- WriteObjectToStream(Items[Index],S);
- end;
- {== TMMEqualizer ==============================================================}
- constructor TMMEqualizer.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FFilters := TMMEQFilterList.Create;
- FFilters.OnChange := FiltersChanged;
- FFilters.FEqualizer := Self;
- FPFilter := nil;
- FPTempFilter:= nil;
- FDescription:= 'Untitled';
- Ffs := defRate;
- FWindow := defWindow;
- FChannel := defChannel;
- FEnabled := defEnabled;
- FOpen := False;
- FUpdating := False;
- FSpectrum := nil;
- FFTLen := 8;
- FFTLength := defFFTLen;
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- destructor TMMEqualizer.Destroy;
- begin
- Close;
- SetSpectrum(nil);
- FFilters.Free;
- inherited Destroy;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Notification(aComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(aComponent, Operation);
- if (Operation = opRemove) then
- begin
- if (aComponent = FSpectrum) then
- FSpectrum := nil;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.PcmOverflow;
- begin
- if assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetPWaveFormat(aValue: PWaveFormatEx);
- begin
- if (aValue <> nil) then
- begin
- if not (csDesigning in ComponentState) then
- if not pcmIsValidFormat(aValue) or (aValue^.wBitsPerSample = 8) then
- raise EMMEqualizerError.Create(LoadResStr(IDS_INVALIDFORMAT));
- SampleRate := aValue^.nSamplesPerSec;
- end;
- inherited SetPWaveFormat(aValue);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SaveToRegIniFile(Ini: TRegIniFile; Section: string);
- var
- i: integer;
- begin
- if (Ini <> nil) then
- begin
- with Ini do
- begin
- WriteInteger(Section, 'FFTLen', FFTLength);
- WriteInteger(Section, 'Samplerate', Samplerate);
- WriteInteger(Section, 'Window', Ord(Window));
- WriteInteger(Section, 'Bands', Filters.Count);
- for i := 0 to Filters.Count-1 do
- with Filters[i] do
- begin
- WriteString(Section, 'Band'+IntToStr(i)+' f1', FloatToStr(f1));
- WriteString(Section, 'Band'+IntToStr(i)+' f2', FloatToStr(f2));
- WriteString(Section, 'Band'+IntToStr(i)+' Gain', FloatToStr(Gain));
- WriteBool(Section, 'Band'+IntToStr(i)+' Enabled', Enabled);
- end;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SaveToIniFileEx(Ini: TIniFile; Section: string);
- var
- i: integer;
- begin
- if (Ini <> nil) then
- begin
- with Ini do
- begin
- WriteInteger(Section, 'FFTLen', FFTLength);
- WriteInteger(Section, 'Samplerate', Samplerate);
- WriteInteger(Section, 'Window', Ord(Window));
- WriteInteger(Section, 'Bands', Filters.Count);
- for i := 0 to Filters.Count-1 do
- with Filters[i] do
- begin
- WriteString(Section, 'Band'+IntToStr(i)+' f1', FloatToStr(f1));
- WriteString(Section, 'Band'+IntToStr(i)+' f2', FloatToStr(f2));
- WriteString(Section, 'Band'+IntToStr(i)+' Gain', FloatToStr(Gain));
- WriteBool(Section, 'Band'+IntToStr(i)+' Enabled', Enabled);
- end;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.ReadFromRegIniFile(Ini: TRegIniFile; Section: string);
- var
- Cnt, i: integer;
- f1,f2,Gain: Float;
- Enabl: Boolean;
- begin
- if (Ini <> nil) then
- begin
- with Ini do
- begin
- i := ReadInteger(Section, 'FFTLen', -1);
- if (i > 0) then
- begin
- Filters.BeginUpdate;
- try
- FUpdating := True;
- Filters.FreeAll;
- FFTLength := ReadInteger(Section, 'FFTLen', defFFTLen);
- Samplerate := ReadInteger(Section, 'Samplerate', defRate);
- Window := TMMFFTWindow(ReadInteger(Section, 'Window', Ord(defWindow)));
- Description := Section;
- Cnt := ReadInteger(Section, 'Bands', 0);
- for i := 0 to Cnt-1 do
- begin
- f1 := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f1', '0')));
- f2 := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f2', '0')));
- Gain := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' Gain', '0')));
- Enabl:= ReadBool(Section, 'Band'+IntToStr(i)+' Enabled', True);
- Filters.AddObject(TMMEQFilter.CreateEx(f1,f2,Gain));
- Filters[i].Enabled := Enabl;
- end;
- finally
- FUpdating := False;
- Filters.EndUpdate;
- end;
- end;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.ReadFromIniFileEx(Ini: TIniFile; Section: string);
- var
- Cnt, i: integer;
- f1,f2,Gain: Float;
- Enabl: Boolean;
- begin
- if (Ini <> nil) then
- begin
- with Ini do
- begin
- i := ReadInteger(Section, 'FFTLen', -1);
- if (i > 0) then
- begin
- Filters.BeginUpdate;
- try
- FUpdating := True;
- Filters.FreeAll;
- FFTLength := ReadInteger(Section, 'FFTLen', defFFTLen);
- Samplerate := ReadInteger(Section, 'Samplerate', defRate);
- Window := TMMFFTWindow(ReadInteger(Section, 'Window', Ord(defWindow)));
- Description := Section;
- Cnt := ReadInteger(Section, 'Bands', 0);
- for i := 0 to Cnt-1 do
- begin
- f1 := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f1', '0')));
- f2 := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' f2', '0')));
- Gain := StrToFloat(CheckFloat(ReadString(Section, 'Band'+IntToStr(i)+' Gain', '0')));
- Enabl:= ReadBool(Section, 'Band'+IntToStr(i)+' Enabled', True);
- Filters.AddObject(TMMEQFilter.CreateEx(f1,f2,Gain));
- Filters[i].Enabled := Enabl;
- end;
- finally
- FUpdating := False;
- Filters.EndUpdate;
- end;
- end;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SaveToIniFile(IniFile: TFileName; Section: string);
- var
- Ini: TIniFile;
- begin
- if (IniFile <> '') then
- begin
- Ini := TIniFile.Create(IniFile);
- try
- Section := 'EQ.'+Section;
- SaveToIniFileEx(Ini, Section);
- finally
- Ini.Free;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.ReadFromIniFile(IniFile: TFileName; Section: string);
- var
- Ini: TInifile;
- begin
- if (IniFile <> '') then
- begin
- Ini := TIniFile.Create(IniFile);
- try
- Section := 'EQ.'+Section;
- ReadFromIniFileEx(Ini,Section);
- finally
- Ini.Free;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetFilters(aValue: TMMEQFilterList);
- begin
- if (aValue <> FFilters) then FFilters.Assign(aValue);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.FilterChanged(Sender: TObject);
- begin
- { setup one equalizer band with the params }
- if not FUpdating then
- begin
- if FOpen then
- with (Sender as TMMEQFilter) do
- begin
- { now update the filter channels }
- if Enabled then
- SetFFTFilterBand(FPFilter,f1,f2,gain)
- else
- SetFFTFilterBand(FPFilter,f1,f2,0);
- end;
- Change;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.FiltersChanged(Sender: TObject);
- begin
- if not FUpdating and (Filters.UpdateCount = 0) then
- begin
- Update;
- Change;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Loaded;
- begin
- inherited Loaded;
- NotifySpectrum;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Change;
- begin
- NotifySpectrum;
- if assigned(FOnChange) then FOnChange(Self);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Update;
- var
- i: integer;
- begin
- { setup the equalizer with the params }
- if FOpen then
- begin
- ResetEQ;
- for i := 0 to Filters.Count-1 do
- with Filters[i] do
- begin
- { now update the filter channels }
- if Enabled then SetFFTFilterBand(FPFilter,f1,f2,Gain);
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.ResetEQ;
- begin
- if FOpen and (FPFilter <> nil) then
- begin
- { reset the equalizer }
- SetFFTFilterBand(FPFilter,0,Ffs/2,0);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.UpdateTempFilter(Init: Boolean);
- var
- wfx: TWaveFormatEx;
- begin
- DoneFFTFilter(FPTempFilter);
- if Init and (FSpectrum <> nil) then
- begin
- pcmBuildWaveHeader(@wfx, 16, 1, Ffs);
- FPTempFilter := InitFFTFilter(@wfx,FFTLen,8192);
- FSpectrum.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
- SetFFTFilterWindow(FPTempFilter,Ord(FWindow));
- NotifySpectrum;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetSpectrum(aValue: TMMSpectrum);
- begin
- if Longint(Self) = Longint(aValue) then exit;
- if (aValue <> FSpectrum) then
- begin
- if (aValue = nil) then
- begin
- FSpectrum.OnNeedData := nil;
- NotifySpectrum;
- UpdateTempFilter(False);
- end;
- FSpectrum := aValue;
- if (FSpectrum <> nil) then
- begin
- UpdateTempFilter(True);
- FSpectrum.Window := fwRectangular;
- FSpectrum.OnNeedData := SpectrumNeedData;
- NotifySpectrum;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.NotifySpectrum;
- begin
- if (FSpectrum = nil) or
- (csLoading in ComponentState) or
- (csReading in ComponentState) then exit;
- FSpectrum.ResetData;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SpectrumNeedData(Sender: TObject);
- var
- i: integer;
- Buf: array[0..8192] of Smallint;
- begin
- if (Sender <> nil) and (FPTempFilter <> nil) then
- with TMMSpectrum(Sender) do
- begin
- { reset the filter }
- SetFFTFilterBand(FPTempFilter,0,Ffs/2, 0);
- for i := 0 to Filters.Count-1 do
- with Filters[i] do
- begin
- { now update the filter bands }
- if Enabled then SetFFTFilterBand(FPTempFilter,f1,f2,Gain);
- end;
- GlobalFillMem(Buf,sizeOf(Buf),0);
- Buf[0] := 21500;
- DoFFTFilter(FPTempFilter, chLeft, @Buf, Max(BytesPerSpectrum,2*FFTLen));
- RefreshPCMData(@Buf);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Assign(Source: TPersistent);
- begin
- if (Source is TMMEqualizer) then
- begin
- if (Source <> nil) then
- begin
- Channel := TMMEqualizer(Source).Channel;
- Enabled := TMMEqualizer(Source).Enabled;
- Description:= TMMEqualizer(Source).Description;
- FFTLength := TMMEqualizer(Source).FFTLength;
- Window := TMMEqualizer(Source).Window;
- Filters := TMMEqualizer(Source).Filters;
- SampleRate := TMMEqualizer(Source).SampleRate;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetChannel(aValue: TMMChannel);
- begin
- if (aValue <> FChannel) then
- begin
- FChannel := aValue;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetSampleRate(aValue: Longint);
- begin
- if (aValue <> Ffs) then
- begin
- Ffs := MinMax(aValue,4000,100000);
- UpdateTempFilter(True);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetWindow(aValue: TMMFFTWindow);
- begin
- if (aValue <> FWindow) then
- begin
- FWindow := aValue;
- if FOpen then SetFFTFilterWindow(FPFilter,Ord(FWindow));
- UpdateTempFilter(True);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetFFTLen(aValue: integer);
- var
- Order: integer;
- begin
- { band wide = (44100/2)/(FFTLen/2) = 172 Hz. for fft(256) }
- { (44100/2)/(FFTLen/2) = 86 Hz wide of band. fft(512) }
- aValue := MinMax(aValue,8,MAX_FFTLEN);
- { Convert FFTLen to a power of 2 }
- Order := 0;
- while aValue > 1 do
- begin
- aValue := aValue shr 1;
- inc(Order);
- end;
- if (Order > 0) then aValue := aValue shl Order;
- if (aValue <> FFTLen) then
- begin
- { re-init the FFTObject with the new FFT-length }
- FFTLen := aValue;
- UpdateTempFilter(True);
- if FOpen then
- begin
- DoneFFTFilter(FPFilter);
- FPFilter := InitFFTFilter(PWaveFormat, FFTLength, FRealBufSize);
- if (FPFilter = nil) then OutOfMemoryError;
- SetFFTFilterWindow(FPFilter,Ord(FWindow));
- Update;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetDescription(aValue: String);
- begin
- if (aValue <> FDescription) then
- begin
- FDescription := aValue;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.SetEnabled(aValue: Boolean);
- begin
- if (aValue <> FEnabled) then
- begin
- FEnabled := aValue;
- Reset;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Open;
- begin
- if not FOpen then
- begin
- if pcmIsValidFormat(PWaveFormat) then
- begin
- FRealBufSize := Max(Max(QUEUE_READ_SIZE,QUEUE_WRITE_SIZE),BufferSize);
- FPFilter := InitFFTFilter(PWaveFormat, FFTLength, FRealBufSize);
- if (FPFilter = nil) then OutOfMemoryError;
- SetFFTFilterWindow(FPFilter,Ord(FWindow));
- FOpen := True;
- Update;
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Reset;
- begin
- if FOpen and (FPFilter <> nil) then
- begin
- ResetFFTFilter(FPFilter);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Close;
- begin
- if FOpen then
- begin
- FOpen := False;
- DoneFFTFilter(FPFilter);
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Process(Buffer: PChar; Length: integer);
- begin
- { process the buffer trough the filter engine }
- if FOpen and (FPFilter <> nil) and FEnabled then
- begin
- if DoFFTFilter(FPFilter, FChannel, Buffer, Length) then
- begin
- if assigned(FOnPcmOverflow) then
- GlobalSynchronize(PcmOverflow);
- end;
- end;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Opened;
- begin
- Open;
- inherited Opened;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Closed;
- begin
- Close;
- inherited Closed;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Started;
- begin
- Update;
- Reset;
- inherited Started;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.Reseting;
- begin
- Reset;
- inherited Reseting;
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.BufferReady(lpwh: PWaveHdr);
- begin
- if FOpen then
- begin
- Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
- end;
- inherited BufferReady(lpwh);
- end;
- {-- TMMEqualizer --------------------------------------------------------------}
- procedure TMMEqualizer.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
- begin
- inherited BufferLoad(lpwh, MoreBuffers);
- if FOpen then
- begin
- Process(lpwh^.lpData, lpwh^.dwBytesRecorded);
- end;
- end;
- initialization
- { register filter class for streaming ! }
- DoRegisterClass(@TMMEQFilter.Load,
- @TMMEQFilter.Store,
- TMMEQFilter);
- end.