MMSpGram.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:78k
- {========================================================================}
- {= (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/index.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: 05.10.98 - 15:53:33 $ =}
- {========================================================================}
- Unit MMSpGram;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- SysUtils,
- Messages,
- Classes,
- Graphics,
- Controls,
- Forms,
- Menus,
- MMSystem,
- MMUtils,
- MMObj,
- MMString,
- MMMath,
- MMMulDiv,
- MMFFT,
- MMRegs,
- MMPCMSup,
- MMDIBCv;
- const
- {$IFDEF CBUILDER3} {$EXTERNALSYM SCALEWIDTH} {$ENDIF}
- SCALEWIDTH = 32;
- {$IFDEF CBUILDER3} {$EXTERNALSYM SCALEFONT} {$ENDIF}
- SCALEFONT = 'ARIAL';
- SCALEFONTSIZE : integer = 10;
- INFOCOLOR : TCOLOR = clWhite;
- {$IFDEF CBUILDER3} {$EXTERNALSYM MIN_COLOR} {$ENDIF}
- MIN_COLOR : Word = 10;
- {$IFDEF CBUILDER3} {$EXTERNALSYM NUM_COLORS} {$ENDIF}
- NUM_COLORS : Word = 236;
- {$IFDEF CBUILDER3} {$EXTERNALSYM MAX_FFTLEN} {$ENDIF}
- MAX_FFTLEN = 4096; { Define the maximum FFT buffer length. }
- type
- EMMSpectrogramError = class(Exception);
- TMMSpectrogramGain = (sgrNone,sgr6db,sgr12db);
- TMMSpectrogramPalette= (spHSV,spThreshold,spBlackWhite,spWhiteBlack,spBone,spCopper,spCool,spHot);
- TMMSpectrogramSelect = procedure(Sender: TObject; Min, Max: Longint) of object;
- PMMSaveBuffer = ^TMMSaveBuffer;
- TMMSaveBuffer = array[0..0,0..0] of integer;
- {-- TMMSpectrogram --------------------------------------------------}
- TMMSpectrogram = class(TMMDIBGraphicControl)
- private
- {$IFDEF WIN32}
- FpFFT : PFFTReal; { the instance for the FFT calculation}
- {$ELSE}
- FFT : TMMFFT; { the object that performs the FFT }
- {$ENDIF}
- FFFTData : PSmallArray;{ Array for FFT data }
- FOldData : PSmallArray;{ Storage for embossed mode }
- FWinBuf : PIntArray; { Array storing windowing function }
- FDisplayVal : PLongArray; { Array storing display values }
- FColorValues : PByteArray; { Array holding color values }
- Fy1 : PIntArray; { Array of bin #'s displayed }
- Fy2 : PIntArray; { Array of terminal bin #'s }
- FFTLen : integer; { Number of points for FFT }
- FSampleRate : Longint; { A/D sampling rate }
- FFreqScaleFactor: Float; { Scalefactor for the horiz. scale }
- FFreqBase : Float; { Base frequency for the display }
- FAmpScale : Float; { scaling factor for amplitude scaling}
- FLogAmp : Boolean; { true for log-based amplitude scale }
- FSensitivy : integer; { here starts the display (db) scaling}
- FWindow : TMMFFTWindow;{ selected window function }
- FEmbossed : Boolean; { enable/disable embossed palette mode}
- FEnabled : Boolean; { Enable or disable Spectrogram }
- FScaleTextColor : TColor; { the text color for the scale }
- FScaleLineColor : TColor; { the line color for the scale }
- FScaleBackColor : TColor; { background color for the scale }
- FSelectColor : TColor; { color for selected range }
- FSelectDotColor : TColor; { border color for selected range }
- FLocatorColor : TColor; { locator color }
- FPalMode : TMMSpectrogramPalette;
- FBits : TMMBits; { b8bit or b16bit }
- FChannel : TMMChannel; { chBoth, chLeft or chRigth }
- FMode : TMMMode; { mMono, mStereo or mQuadro }
- FBytes : Longint; { calculated data bytes p. spectrogram}
- FGain : TMMSpectrogramGain;{ Amount of db/octave gain }
- FOldShowHint : Boolean; { save ShowHint propertie }
- FShowInfo : Boolean; { show the freq info or not }
- FShowInfoHint : Boolean; { mouse is down, show the info hint }
- FDrawScale : Boolean; { draw the scale or not }
- FWidth : integer; { calculated width without border }
- FHeight : integer; { calculated height without border }
- FClientRect : TRect; { calculated beveled Rect }
- Fx1 : integer; { horiz. position counter for display }
- Fx2 : integer; { horizontal position counter for bar }
- FNumScaleSteps : integer; { pre-calculated number of scale steps}
- FBarWidth : integer; { width for the moving bar }
- FBarColor : TColor; { the color for the moving bar }
- FBarTickColor : TColor; { the color for the ticks on the bar }
- FNeedReset : Boolean; { the spectrum needs a reset }
- FAccelerate : Boolean; { accelerate the display refresh }
- FScroll : Boolean; { scroll the display or not }
- FSaveData : Boolean; { save the actual spectrum data }
- FSaveBuffer : PMMSaveBuffer;
- FSelectStart : Longint; { start pos for selected region }
- FSelectEnd : Longint; { end pos for selected region }
- FLocator : Longint; { current locator position }
- FDrawing : Boolean;
- FOldCursor : TCursor;
- FOrigin : TRect;
- FMoveRect : TRect;
- FLocked : Boolean;
- FUseSelection : Boolean;
- { Events }
- FOnPcmOverflow : TNotifyEvent;
- FOnSelecting : TMMSpectrogramSelect;
- FOnSelectEnd : TMMSpectrogramSelect;
- procedure CreateDataBuffers(Length: Cardinal);
- procedure FreeDataBuffers;
- procedure CreateArrays(Size: Cardinal);
- procedure FreeArrays;
- procedure SetBytesPerSpectrogram;
- procedure SetupYScale;
- procedure CalcScaleSteps;
- procedure CalcMagnitude(MagnitudeForm: Boolean);
- procedure DrawInfo(Pos: TPoint);
- procedure DrawFrequencyScale;
- procedure DrawData(pDispData: PLongArray);
- procedure DrawBar;
- procedure DrawSelection(aCanvas: TMMDIBCanvas; sStart, sEnd: Longint;
- sColor: TColor; Solid: Boolean);
- procedure DrawLocator(aCanvas: TMMDIBCanvas; aPos: Longint; aColor: TColor);
- procedure DrawSpectrogram(ClearBackGround: Boolean);
- procedure AdjustSize(var W, H: Integer);
- procedure AdjustBounds;
- procedure SetFFTLen(aLength: integer);
- procedure SetWindow(aValue: TMMFFTWindow);
- procedure SetPalMode(aValue: TMMSpectrogramPalette);
- procedure SetEmbossed(aValue: Boolean);
- procedure SetLogAmp(aValue: Boolean);
- procedure SetFreqScale(aValue: integer);
- function GetFreqScale: integer;
- procedure SetFreqBase(aValue: integer);
- function GetFreqBase: integer;
- procedure SetAmplitudeScale(aValue: integer);
- function GetAmplitudeScale: integer;
- procedure SetAccelerate(aValue: Boolean);
- procedure SetDrawScale(aValue: Boolean);
- procedure SetEnabled(aValue: Boolean);
- procedure SetColors(Index: Integer; Value: TColor);
- procedure SetBarWidth(aValue: integer);
- procedure SetPCMWaveFormat(wf: TPCMWaveFormat);
- function GetPCMWaveFormat: TPCMWaveFormat;
- procedure SetBits(aValue: TMMBits);
- procedure SetChannel(aValue: TMMChannel);
- procedure SetMode(aValue: TMMMode);
- procedure SetSampleRate(aValue: Longint);
- procedure SetGain(aValue: TMMSpectrogramGain);
- procedure SetSensitivy(aValue: integer);
- procedure SetScroll(aValue: Boolean);
- function GetScaleBackColor: TColor;
- procedure SetLocator(aValue: Longint);
- procedure SetSaveData(aValue: Boolean);
-
- protected
- procedure ChangeDesigning(aValue: Boolean); override;
- procedure Paint; override;
- procedure Loaded; override;
- procedure PcmOverflow; dynamic;
- procedure SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
- procedure Changed; override;
- procedure Selecting(Min, Max: Longint); dynamic;
- procedure SelectEnd(Min, Max: Longint); dynamic;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function GetFrequency(Pos: TPoint): Float;
- procedure SetPalette(LogPal: PLogPalette);
- procedure RefreshPCMData(PCMData: Pointer);
- procedure RefreshFFTData(FFTData: Pointer);
- procedure RefreshMagnitudeData(MagData: Pointer);
- procedure ResetData;
- property ColorValues: PByteArray read FColorValues;
- property BytesPerSpectrogram: Longint read FBytes;
- property PCMWaveFormat: TPCMWaveFormat read GetPCMWaveFormat write SetPCMWaveFormat;
- property FFTData: PSmallArray read FFFTData;
- procedure Select(sStart, sEnd: Longint; Redraw: Boolean);
- property SelectionStart: Longint read FSelectStart;
- property SelectionEnd: Longint read FSelectEnd;
- property Locator: Longint read Flocator write SetLocator default -1;
- function IsLocator(X: integer): Boolean;
- function IsSelectStart(X: integer): Boolean;
- function IsSelectEnd(X: integer): Boolean;
- function IsInSelection(X: integer): Boolean;
- property SaveData: Boolean read FSaveData write SetSaveData default False;
- published
- { Events }
- property OnClick;
- property OnDblClick;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDrag;
- property OnStartDrag;
- property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
- property OnSelecting: TMMSpectrogramSelect read FOnSelecting write FOnSelecting;
- property OnSelectEnd: TMMSpectrogramSelect read FOnSelectEnd write FOnSelectEnd;
- property Align;
- property Bevel;
- property PopupMenu;
- property ParentShowHint;
- property ShowHint;
- property Visible;
- property Cursor default crCross;
- property PaletteRealize default True;
- property PaletteMapped;
- property ShowInfo: Boolean read FShowInfo write FShowInfo default True;
- property Enabled: Boolean read FEnabled write SetEnabled default True;
- property DrawScale: Boolean read FDrawScale write SetDrawScale default False;
- property Height default 90;
- property Width default 194;
- property Accelerate: Boolean read FAccelerate write SetAccelerate default True;
- property Scroll: Boolean read FScroll write SetScroll default False;
- property ScaleTextColor: TColor index 0 read FScaleTextColor write SetColors default clBlack;
- property ScaleLineColor: TColor index 1 read FScaleLineColor write SetColors default clBlack;
- property BarColor: TColor index 2 read FBarColor write SetColors default clGray;
- property BarTickColor: TColor index 3 read FBarTickColor write SetColors default clWhite;
- {$IFDEF BUILD_ACTIVEX}
- property ScaleBackColor: TColor index 4 read FScaleBackColor write SetColors default clBtnface;
- {$ENDIF}
- property SelectionColor: TColor index 5 read FSelectColor write SetColors default clRed;
- property SelectionDotColor: TColor index 6 read FSelectDotColor write SetColors default clRed;
- property LocatorColor: TColor index 7 read FLocatorColor write SetColors default clYellow;
- property BarWidth: integer read FBarWidth write SetBarWidth default 5;
- property Mode: TMMMode read FMode write SetMode default mMono;
- property BitLength: TMMBits read FBits write SetBits default b8bit;
- property Channel: TMMChannel read FChannel write SetChannel default chBoth;
- property SampleRate: Longint read FSampleRate write SetSampleRate default 11025;
- property Gain: TMMSpectrogramGain read FGain write SetGain default sgrNone;
- property FFTLength: integer read FFTLen write SetFFTLen default 128;
- property Window: TMMFFTWindow read FWindow write SetWindow default fwHamming;
- property LogAmp: Boolean read FLogAmp write SetLogAmp default False;
- property Embossed: Boolean read FEmbossed write SetEmbossed default False;
- property AmplitudeScale: integer read GetAmplitudeScale write SetAmplitudeScale default 100;
- property FrequencyBase: integer read GetFreqBase write SetFreqBase default 0;
- property FrequencyScale: integer read GetFreqScale write SetFreqScale default 1;
- property Sensitivy: integer read FSensitivy write SetSensitivy default -90;
- property PaletteTyp: TMMSpectrogramPalette read FPalMode write SetPalMode default spThreshold;
- property Locked: Boolean read FLocked write FLocked default False;
- property UseSelection: Boolean read FUseSelection write FUseSelection default False;
- end;
- implementation
- uses consts;
- const
- CreateCount: Longint = 0;
- ControlList: TList = nil;
- SaveDC : HDC = 0;
- SaveBitmap : HBitmap = 0;
- SaveWidth : integer = 0;
- SaveHeight : integer = 0;
- SaveInfoPos: TPoint = (X:0;Y:0);
- OldBitmap : HBitmap = 0;
- OldPalette : HPalette= 0;
- {------------------------------------------------------------------------}
- procedure AddSpectrogram(Spectrogram: TMMSpectrogram);
- begin
- inc(CreateCount);
- if (CreateCount = 1) then
- begin
- ControlList := TList.Create;
- end;
- if ControlList.IndexOf(Spectrogram) = -1 then
- ControlList.Add(Spectrogram);
- end;
- {------------------------------------------------------------------------}
- procedure RemoveSpectrogram(Spectrogram: TMMSpectrogram);
- begin
- ControlList.Remove(Spectrogram);
- ControlList.Pack;
- dec(CreateCount);
- if (CreateCount = 0) then
- begin
- ControlList.Free;
- ControlList := nil;
- end;
- end;
- {------------------------------------------------------------------------}
- procedure ResetSpectrograms(Spectrogram: TMMSpectrogram);
- var
- i: integer;
- begin
- if (ControlList <> nil) and (ControlList.Count > 0) then
- begin
- for i := 0 to ControlList.Count-1 do
- if (ControlList.Items[i] <> Spectrogram) then
- TMMSpectrogram(ControlList.Items[i]).FNeedReset := True;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- constructor TMMSpectrogram.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- CreateDataBuffers(MAX_FFTLEN);
- PaletteRealize := True;
- {$IFDEF WIN32}
- FpFFT := InitRealFFT(8);
- {$ELSE}
- FFT := TMMFFT.Create;
- {$ENDIF}
- FFTLen := 8;
- FAccelerate := True;
- FSampleRate := 11025;
- FChannel := chBoth;
- FBits := b8bit;
- FMode := mMono;
- FGain := sgrNone;
- FEmbossed := False;
- FWindow := fwHamming;
- FFreqScaleFactor := 1.0;
- FFreqBase := 0;
- FAmpScale := 1.0;
- FLogAmp := False;
- FSensitivy := -90;
- FEnabled := True;
- FPalMode := spThreshold;
- Color := clBlack;
- FScaleTextColor := clBlack;
- FScaleLineColor:= clBlack;
- FScaleBackColor := clBtnFace;
- FBarWidth := 5;
- FBarColor := clGray;
- FBarTickColor := clWhite;
- FDrawScale := False;
- Fx1 := -FBarWidth;
- Fx2 := 0;
- FNeedReset := False;
- FScroll := False;
- FShowInfoHint := False;
- FShowInfo := True;
- FSaveData := False;
- FSelectStart := -1;
- FSelectEnd := -1;
- FLocator := -1;
- FSelectColor := clRed;
- FSelectDotColor := clRed;
- FLocatorColor := clYellow;
- FDrawing := False;
- FLocked := False;
- FUseSelection := False;
- FSaveBuffer := nil;
- Height := 90;
- Width := 194;
- Cursor := crCross;
- FFTLength := 128;
- if not (csDesigning in ComponentState) then
- begin
- { update the spectrogram list }
- AddSpectrogram(Self);
- end;
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Destructor TMMSpectrogram.Destroy;
- begin
- if not (csDesigning in ComponentState) then
- begin
- { update the spectrogram list }
- RemoveSpectrogram(Self);
- end;
- FreeDataBuffers;
- FreeArrays;
- {$IFDEF WIN32}
- DoneRealFFT(FpFFT);
- {$ELSE}
- FFT.Free;
- {$ENDIF}
- inherited Destroy;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.ChangeDesigning(aValue: Boolean);
- begin
- inherited ChangeDesigning(aValue);
- if not (csDesigning in ComponentState) then
- begin
- { update the spectrogram list }
- AddSpectrogram(Self);
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.PcmOverflow;
- begin
- if Assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.CreateDataBuffers(Length: Cardinal);
- begin
- if (Length > 0) then
- begin
- FFFTData := GlobalAllocMem(Length * sizeOf(SmallInt));
- FWinBuf := GlobalAllocMem(Length * sizeOf(Integer));
- FOldData := GlobalAllocMem((Length div 2) * sizeOf(SmallInt));
- FDisplayVal:= GlobalAllocMem((Length div 2) * sizeOf(Long));
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.FreeDataBuffers;
- begin
- GlobalFreeMem(Pointer(FFFTData));
- GlobalFreeMem(Pointer(FWinBuf));
- GlobalFreeMem(Pointer(FOldData));
- GlobalFreeMem(Pointer(FDisplayVal));
- GlobalFreeMem(Pointer(FSaveBuffer));
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.CreateArrays(Size: Cardinal);
- begin
- if (Size > 0) then
- begin
- Fy1 := GlobalAllocMem(Size * sizeOf(Integer));
- Fy2 := GlobalAllocMem(Size * sizeOf(Integer));
- FColorValues := GlobalAllocMem(Size * sizeOf(Byte));
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.FreeArrays;
- begin
- GlobalFreeMem(Pointer(Fy1));
- GlobalFreeMem(Pointer(Fy2));
- GlobalFreeMem(Pointer(FColorValues));
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.ResetData;
- var
- P: TPoint;
- begin
- if FShowInfoHint then
- begin
- GetCursorPos(P);
- P := ScreenToClient(P);
- Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));
- end;
- FNeedReset := True;
- FSelectStart := -1;
- FSelectEnd := -1;
- FLocator := -1;
- Fx1 := -BarWidth;//Max(-FBarWidth,0);
- Fx2 := 0;
- if (FSaveBuffer <> nil) then
- FillChar(FSaveBuffer^,(MAX_FFTLEN div 2) * sizeOf(Long)*FWidth,0);
- Refresh;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetFFTLen(aLength: integer);
- var
- Order: integer;
- begin
- aLength := MinMax(aLength,8,MAX_FFTLEN);
- { Convert FFTLen to a power of 2 }
- Order := 0;
- while aLength > 1 do
- begin
- aLength := aLength shr 1;
- inc(Order);
- end;
- if (Order > 0) then aLength := aLength shl Order;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK1}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- if (aLength <> FFTLen) then
- begin
- { re-init the FFTObject with the new FFT-length }
- {$IFDEF WIN32}
- DoneRealFFT(FpFFT);
- FpFFT := InitRealFFT(Order);
- FFTLen := aLength;
- GenWindowTableInt(FWinBuf,Ord(FWindow),Trunc(Log2(FFTLen)));
- {$ELSE}
- FFT.FFTLength := aLength;
- FFTLen := aLength;
- GenWindowTableInt(FWinBuf,Ord(FWindow),Trunc(Log2(FFTLen)));
- {$ENDIF}
- { Re-initialize the display }
- SetupYScale;
- SetBytesPerSpectrogram;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetWindow(aValue: TMMFFTWindow);
- begin
- if (aValue <> FWindow) then
- begin
- FWindow := aValue;
- GenWindowTableInt(FWinBuf,Ord(FWindow),Trunc(Log2(FFTLen)));
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetSampleRate(aValue: Longint);
- begin
- if (aValue <> FSampleRate) then
- begin
- FSampleRate := MinMax(aValue, 8000, 100000);
- { Re-initialize the display }
- SetupYScale;
- { calc the number of scale steps }
- CalcScaleSteps;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetLogAmp(aValue: Boolean);
- begin
- { Toggle linear/logarithmic amplitude axis }
- if (aValue <> FLogAmp) then
- begin
- FLogAmp := aValue;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetEnabled(aValue: Boolean);
- begin
- if (aValue <> FEnabled) then
- begin
- FEnabled := aValue;
- { inherited Enabled := Value }
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetBarWidth(aValue: integer);
- begin
- if (aValue <> FBarWidth) then
- begin
- FBarWidth := Max(aValue,0);
- Invalidate;
- end;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK2}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetSaveData(aValue: Boolean);
- begin
- if (aValue <> FSaveData) then
- begin
- if (FSaveBuffer <> nil) then
- GlobalFreeMem(Pointer(FSaveBuffer));
- FSaveData := aValue;
- if FSaveData then
- FSaveBuffer := GlobalAllocMem((MAX_FFTLEN div 2) * sizeOf(Long)*FWidth);
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.Loaded;
- begin
- inherited Loaded;
- SetupYScale;
- SetPalMode(FPalMode);
- FastDraw(DrawSpectrogram,True);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.AdjustSize(var W, H: Integer);
- begin
- if FDrawScale then
- W := Max(W,2*SCALEWIDTH+2*BevelExtend+5)
- else
- W := Max(W,2*BevelExtend+5);
- H := Max(H,2*BevelExtend+5);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.AdjustBounds;
- var
- W, H: Integer;
- begin
- W := Width;
- H := Height;
- AdjustSize(W, H);
- if (W <> Width) or (H <> Height) then SetBounds(Left, Top, W, H)
- else Changed;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
- var
- W, H: Integer;
- begin
- W := aWidth;
- H := aHeight;
- AdjustSize (W, H);
- inherited SetBounds(aLeft, aTop, W, H);
- Changed;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.Changed;
- begin
- FClientRect := Rect(0,0,Width,Height);
- if FDrawScale then
- begin
- { make place for the scale }
- InflateRect(FClientRect, -SCALEWIDTH,0);
- end;
- { and now for the bevel }
- InflateRect(FClientRect, -Bevel.BevelExtend, -Bevel.BevelExtend);
- { save the real height and width }
- FWidth := Max(FClientRect.Right - FClientRect.Left,4);
- FHeight := Max(FClientRect.Bottom - FClientRect.Top,4);
- FreeArrays; { adjust the dyn.array size }
- CreateArrays(FHeight);
- DIBCanvas.SetBounds(0,0,FWidth,FHeight);
- if (FSaveBuffer <> nil) then
- begin
- GlobalFreeMem(Pointer(FSaveBuffer));
- FSaveBuffer := GlobalAllocMem((MAX_FFTLEN div 2) * sizeOf(Long)*FWidth);
- end;
- SetBytesPerSpectrogram; { calc the new bytes per Scope }
- SetupYScale; { recalc the scalings }
- CalcScaleSteps;
- ResetData;
- inherited Changed;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetBytesPerSpectrogram;
- begin
- FBytes := (Ord(FBits)+1) * (Ord(FMode)+1) * FFTLen;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetPCMWaveFormat(wf: TPCMWaveFormat);
- var
- pwfx: PWaveFormatEx;
- begin
- pwfx := @wf;
- if not pcmIsValidFormat(pwfx) then
- raise EMMSpectrogramError.Create(LoadResStr(IDS_INVALIDFORMAT));
- SampleRate := pwfx^.nSamplesPerSec;
- BitLength := TMMBits(pwfx^.wBitsPerSample div 8 - 1);
- Mode := TMMMode(pwfx^.nChannels-1);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetPCMWaveFormat: TPCMWaveFormat;
- var
- wfx: TWaveFormatEx;
- begin
- pcmBuildWaveHeader(@wfx, (Ord(FBits)+1)*8, Ord(FMode)+1, SampleRate);
- Result := PPCMWaveFormat(@wfx)^;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetBits(aValue: TMMBits);
- begin
- if (aValue <> FBits) then
- begin
- FBits := aValue;
- SetBytesPerSpectrogram;
- Invalidate;
- end;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK3}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetChannel(aValue: TMMChannel);
- begin
- if (aValue <> FChannel) then
- begin
- FChannel := aValue;
- SetBytesPerSpectrogram;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetMode(aValue: TMMMode);
- begin
- if (aValue <> FMode) then
- begin
- FMode := aValue;
- SetBytesPerSpectrogram;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetGain(aValue: TMMSpectrogramGain);
- begin
- if (aValue <> FGain) then
- begin
- FGain := aValue;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.Select(sStart, sEnd: Longint; Redraw: Boolean);
- var
- oldStart,oldEnd: Longint;
- begin
- oldStart:= FSelectStart;
- oldEnd := FSElectEnd;
- if (sStart <> FSelectStart) then
- begin
- if (sStart < 0) then sStart := -1;
- if (sStart > FWidth) then sStart := FWidth;
- FSelectStart := sStart;
- end;
- if (sEnd <> FSelectEnd) then
- begin
- if (sEnd < 0) then sEnd := -1;
- if (sEnd > FWidth) then sEnd := FWidth;
- FSelectEnd := sEnd;
- end;
- if (FSelectStart > FSelectEnd) then
- begin
- SwapLong(FSelectStart,FSelectEnd);
- end;
- if (FSelectEnd - FSelectStart <= 0) then
- begin
- FSelectStart := -1;
- FSelectEnd := -1;
- end;
- if Redraw and ((oldStart <> FSelectStart) or (oldEnd <> FSelectEnd)) then
- Refresh;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetLocator(aValue: Longint);
- var
- oldLoc: Longint;
- begin
- oldLoc := FLocator;
- if (aValue <> FLocator) then
- begin
- if (aValue < 0) then aValue := -1;
- if (aValue > FWidth) then aValue := FWidth;
- FLocator := aValue;
- end;
- if (oldLoc <> FLocator) then
- Refresh;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetAmplitudeScale;
- begin
- { Change the amplitude scale factor }
- aValue := MinMax(aValue, 0, 1000);
- if (aValue <> GetAmplitudeScale) then
- begin
- FAmpScale := 0.01*aValue;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetAmplitudeScale: integer;
- begin
- Result := Round(FAmpScale/0.01);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetFreqScale(aValue: integer);
- begin
- aValue := MinMax(aValue,1,16);
- if (aValue <> Trunc(FFreqScaleFactor)) then
- begin
- FFreqScaleFactor := aValue;
- { Re-initialize the display }
- SetupYScale;
- { calc the number of scale steps }
- CalcScaleSteps;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetFreqScale: integer;
- begin
- Result := Trunc(FFreqScaleFactor);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetFreqBase(aValue: integer);
- begin
- aValue := Max(aValue,0);
- if (aValue <> Trunc(FFreqBase)) then
- begin
- FFreqBase := aValue;
- { Re-initialize the display }
- SetupYScale;
- { calc the number of scale steps }
- CalcScaleSteps;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetFreqBase: integer;
- begin
- Result := Trunc(FFreqBase);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetSensitivy(aValue: integer);
- begin
- aValue := MinMax(aValue, -90, -9);
- if (aValue <> FSensitivy) then
- begin
- FSensitivy := aValue;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetDrawScale(aValue: Boolean);
- begin
- if (aValue <> FDrawScale) then
- begin
- FDrawScale := aValue;
- AdjustBounds;
- Invalidate;
- end;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK2}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetAccelerate(aValue: Boolean);
- begin
- if (aValue <> FAccelerate) then
- begin
- FAccelerate := aValue;
- if not FAccelerate and FScroll then Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetEmbossed(aValue: Boolean);
- begin
- if (aValue <> FEmbossed) then
- begin
- FEmbossed := aValue;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetScroll(aValue: Boolean);
- begin
- if (aValue <> FScroll) then
- begin
- FScroll := aValue;
- Invalidate;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.SetColors(Index: Integer; Value: TColor);
- begin
- case Index of
- 0: if FScaleTextColor = Value then exit else FScaleTextColor := Value;
- 1: if FScaleLineColor = Value then exit else FScaleLineColor := Value;
- 2: if FBarColor = Value then exit else FBarColor := Value;
- 3: if FBarTickColor = Value then exit else FBarTickColor := Value;
- 4: if FScaleBackColor = Value then exit else FScaleBackColor := Value;
- 5: if FSelectColor = Value then exit else FSelectColor := Value;
- 6: if FSelectDotColor = Value then exit else FSelectDotColor := Value;
- 7: if FLocatorColor = Value then exit else FLocatorColor := Value;
- end;
- Invalidate;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK1}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetPalette(LogPal: PLogPalette);
- begin
- Refresh;
- DIBCanvas.SetLogPalette(LogPal);
- Invalidate;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetPalMode(aValue: TMMSpectrogramPalette);
- type
- { Logical Palette }
- TLogPal = packed record
- palVersion: Word;
- palNumEntries: Word;
- palEntry: array[0..255] of TPaletteEntry;
- end;
- var
- i,clr: Longint;
- LogPal: TLogPal;
- begin
- FPalMode := aValue;
- if not (csLoading in ComponentState) and
- not (csReading in ComponentState) then
- begin
- FillChar(LogPal, sizeOf(LogPal),0);
- with LogPal do
- begin
- palVersion := $300;
- palNumEntries := 256;
- for i := MIN_COLOR to MIN_COLOR+NUM_COLORS-1 do
- begin
- clr := (i-MIN_COLOR)*256 div NUM_COLORS;
- case FPalMode of
- spHSV:
- begin
- if (clr < 64) then
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := clr*4;
- palEntry[i].peBlue := 255;
- end
- else if (clr < 128) then
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := 255;
- palEntry[i].peBlue := 510-clr*4;
- end
- else if (clr < 192) then
- begin
- palEntry[i].peRed := clr*4-510;
- palEntry[i].peGreen := 255;
- palEntry[i].peBlue := 0;
- end
- else
- begin
- palEntry[i].peRed := 255;
- palEntry[i].peGreen := 1020-clr*4;
- palEntry[i].peBlue := 0;
- end;
- end;
- spThreshold:
- begin
- if (clr < 16) then
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := 0;
- palEntry[i].peBlue := 0;
- end
- else if (clr < 64) then
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := clr*4;
- palEntry[i].peBlue := 255;
- end
- else if (clr < 128) then
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := 255;
- palEntry[i].peBlue := 510-clr*4;
- end
- else if (clr < 192) then
- begin
- palEntry[i].peRed := clr*4-510;
- palEntry[i].peGreen := 255;
- palEntry[i].peBlue := 0;
- end
- else
- begin
- palEntry[i].peRed := 255;
- palEntry[i].peGreen := 1020-clr*4;
- palEntry[i].peBlue := 0;
- end;
- end;
- spCool:
- begin
- palEntry[i].peRed := clr;
- palEntry[i].peGreen := 255-clr;
- palEntry[i].peBlue := 255;
- end;
- spHot:
- begin
- if (clr < 96) then
- begin
- palEntry[i].peRed := Trunc(clr*2.66667+0.5);
- palEntry[i].peGreen := 0;
- palEntry[i].peBlue := 0;
- end
- else if (clr < 192) then
- begin
- palEntry[i].peRed := 255;
- palEntry[i].peGreen := Trunc(clr*2.66667-254);
- palEntry[i].peBlue := 0;
- end
- else
- begin
- palEntry[i].peRed := 255;
- palEntry[i].peGreen := 255;
- palEntry[i].peBlue := Trunc(clr*4.0-766.0);
- end;
- end;
- spBone:
- begin
- if (clr < 96) then
- begin
- palEntry[i].peRed := Trunc(clr*0.88889);
- palEntry[i].peGreen := Trunc(clr*0.88889);
- palEntry[i].peBlue := Trunc(clr*1.20000);
- end
- else if (clr < 192) then
- begin
- palEntry[i].peRed := Trunc(clr*0.88889);
- palEntry[i].peGreen := Trunc(clr*1.20000-29);
- palEntry[i].peBlue := Trunc(clr*0.88889+29);
- end
- else
- begin
- palEntry[i].peRed := Trunc(clr*1.20000-60);
- palEntry[i].peGreen := Trunc(clr*0.88889+29);
- palEntry[i].peBlue := Trunc(clr*0.88889+29);
- end;
- end;
- spCopper:
- begin
- if (clr < 208) then
- begin
- palEntry[i].peRed := Trunc(clr*1.23);
- palEntry[i].peGreen := Trunc(clr*0.78);
- palEntry[i].peBlue := Trunc(clr*0.5);
- end
- else
- begin
- palEntry[i].peRed := 255;
- palEntry[i].peGreen := Trunc(clr*0.78);
- palEntry[i].peBlue := Trunc(clr*0.5);
- end;
- end;
- spBlackWhite:
- begin
- palEntry[i].peRed := clr;
- palEntry[i].peGreen := clr;
- palEntry[i].peBlue := clr;
- end;
- spWhiteBlack:
- begin
- palEntry[i].peRed := 255-clr;
- palEntry[i].peGreen := 255-clr;
- palEntry[i].peBlue := 255-clr;
- end;
- end;
- end;
- end;
- SetPalette(@LogPal);
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SetupYScale;
- var
- i,ival: Long;
- FFTBase: Float;
- begin
- { Setup Y axis }
- if not(csLoading in ComponentState) then
- begin
- { Do some range checking on the base and scale factors }
- FFreqBase := MinMaxR(FFreqBase,0,FSampleRate/2-1000);
- if FFreqBase+(FSampleRate/2-FFreqScaleFactor*FFreqBase)/FFreqScaleFactor > FSampleRate/2 then
- FFreqBase := FSampleRate/2-(FSampleRate/2-FFreqScaleFactor*FFreqBase)/FFreqScaleFactor-1000;
- FFTBase := FFreqBase/FSampleRate*FFTLen;
- { Initialize graph y scale (linear or logarithmic).
- This array points to the bin to be plotted on a given row.}
- for i := 0 to FHeight-1 do
- begin
- ival := Floor(0.01+FFTBase+(i/FHeight*
- (FFTLen/2-FFreqScaleFactor*FFTBase))/FFreqScaleFactor);
- ival := MinMax(ival,0,FFTLen div 2-1);
- Fy1^[i] := ival;
- if (i > 0) then Fy2^[i-1] := ival;
- end;
- { Compute the ending locations for lines holding multiple bins }
- for i := 0 to FHeight-1 do
- if (Fy2^[i] <= (Fy1^[i]+1)) then Fy2^[i] := 0;
- { if lines are repeated on the screen, flag this so that we don't
- have to recompute the y values. }
- for i := FHeight-1 downTo 1 do
- begin
- if (Fy1^[i] = Fy1^[i-1]) then
- begin
- Fy1^[i] := -1;
- Fy2^[i]:= 0;
- end;
- end;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.RefreshPCMData(PCMData: Pointer);
- var
- Value: Longint;
- i: Integer;
- ReIndex: integer;
- Back1, Back2: Long; { Variables for differencing }
- {$IFDEF WIN32}
- fTemp: array[0..MAX_FFTLEN] of Float;
- {$ELSE}
- fTemp: array[0..MAX_FFTLEN] of Smallint;
- {$ENDIF}
- begin
- if FEnabled and Visible and not FShowInfoHint then
- begin
- ReIndex := Ord(FChannel)-1;
- if (FGain = sgrNone) then
- begin
- { perform windowing on sample Data from PCMData to FFFTData }
- if (FBits = b8bit) then
- if (FMode = mMono) then
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-128,FWinBuf^[i],128);
- end
- else if (FChannel = chBoth) then
- for i := 0 to FFTLen-1 do
- begin
- Value := (Word(PByteArray(PCMData)^[i+i])+PByteArray(PCMData)^[i+i+1])div 2;
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-128,FWinBuf^[i],128);
- end
- else
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i+i+ReIndex];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-128,FWinBuf^[i],128);
- end
- else
- if (FMode = mMono) then
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value,FWinBuf^[i],32768);
- end
- else if (FChannel = chBoth) then
- for i := 0 to FFTLen-1 do
- begin
- Value := (Long(PSmallArray(PCMData)^[i+i])+PSmallArray(PCMData)^[i+i+1])div 2;
- if Value >= 32766 then PcmOverflow;
- fTemp[i] := MulDiv32(Value,FWinBuf^[i],32768);
- end
- else
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i+i+ReIndex];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value,FWinBuf^[i],32768);
- end;
- end
- else if (FGain = sgr6db) then
- begin
- { perform windowing on sample Data from PCMData to FFFTData }
- if (FBits = b8bit) then
- begin
- if (FMode = mMono) then
- begin
- Back1 := PByteArray(PCMData)^[0];
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],128);
- Back1 := Value;
- end;
- end
- else if (FChannel = chBoth) then
- begin
- Back1 := PByteArray(PCMData)^[0];
- for i := 0 to FFTLen-1 do
- begin
- Value := (Word(PByteArray(PCMData)^[i+i])+PByteArray(PCMData)^[i+i+1])div 2;
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],128);
- Back1 := Value;
- end;
- end
- else
- begin
- Back1 := PByteArray(PCMData)^[ReIndex];
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i+i+ReIndex];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],128);
- Back1 := Value;
- end;
- end;
- end
- else
- begin
- if (FMode = mMono) then
- begin
- Back1 := PSmallArray(PCMData)^[0];
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],32768);
- Back1 := Value;
- end;
- end
- else if (FChannel = chBoth) then
- begin
- Back1 := PSmallArray(PCMData)^[0];
- for i := 0 to FFTLen-1 do
- begin
- Value := (Long(PSmallArray(PCMData)^[i+i])+PSmallArray(PCMData)^[i+i+1])div 2;
- if Value >= 32766 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],32768);
- Back1 := Value;
- end;
- end
- else
- begin
- Back1 := PSmallArray(PCMData)^[ReIndex];
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i+i+ReIndex];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-Back1,FWinBuf^[i],32768);
- Back1 := Value;
- end;
- end;
- end;
- end
- else { Deriv = 2 }
- begin
- { perform windowing on sample Data from PCMData to FFFTData }
- if (FBits = b8bit) then
- begin
- if (FMode = mMono) then
- begin
- Back1 := PByteArray(PCMData)^[0];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],128);
- Back2 := Back1;
- Back1 := Value;
- end;
- end
- else if (FChannel = chBoth) then
- begin
- Back1 := PByteArray(PCMData)^[0];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := (Word(PByteArray(PCMData)^[i+i])+PByteArray(PCMData)^[i+i+1])div 2;
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],128);
- Back2 := Back1;
- Back1 := Value;
- end;
- end
- else
- begin
- Back1 := PByteArray(PCMData)^[ReIndex];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := PByteArray(PCMData)^[i+i+ReIndex];
- if Value >= 255 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],128);
- Back2 := Back1;
- Back1 := Value;
- end;
- end;
- end
- else
- begin
- if (FMode = mMono) then
- begin
- Back1 := PSmallArray(PCMData)^[0];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],32768);
- Back2 := Back1;
- Back1 := Value;
- end;
- end
- else if (FChannel = chBoth) then
- begin
- Back1 := PSmallArray(PCMData)^[0];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := (Long(PSmallArray(PCMData)^[i+i])+PSmallArray(PCMData)^[i+i+1])div 2;
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],32768);
- Back2 := Back1;
- Back1 := Value;
- end;
- end
- else
- begin
- Back1 := PSmallArray(PCMData)^[ReIndex];
- Back2 := Back1;
- for i := 0 to FFTLen-1 do
- begin
- Value := PSmallArray(PCMData)^[i+i+ReIndex];
- if Value >= 32767 then PcmOverflow;
- fTemp[i] := MulDiv32(Value-2*Back1+Back2,FWinBuf^[i],32768);
- Back2 := Back1;
- Back1 := Value;
- end;
- end;
- end;
- end;
- fTemp[FFTLen] := 0;
- { calc the FFT }
- {$IFDEF WIN32}
- DoRealFFT(FpFFT,@fTemp,1);
- for i := 0 to FFTLen do FFFTData^[i] := Trunc(fTemp[i]/(FFTLen div 2));
- {$ELSE}
- for i := 0 to FFTLen do FFFTData^[i] := fTemp[i];
- FFT.CalcFFT(Pointer(FFFTData));
- {$ENDIF}
- { calc the magnitude }
- CalcMagnitude(False);
- { next, put this data up on the display }
- FastDraw(DrawSpectrogram,False);
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.RefreshFFTData(FFTData: Pointer);
- begin
- Move(PByte(FFTData)^, FFFTData^, FFTLen*sizeOf(SmallInt));
- { calc the magnitude }
- CalcMagnitude(False);
- { next, put this data up on the display }
- FastDraw(DrawSpectrogram,False);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.RefreshMagnitudeData(MagData: Pointer);
- begin
- Move(PByte(MagData)^, FFFTData^, FFTLen*sizeOf(SmallInt));
- { calc display values }
- CalcMagnitude(True);
- { next, put this data up on the display }
- FastDraw(DrawSpectrogram,False);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.CalcMagnitude(MagnitudeForm: Boolean);
- var
- i: integer;
- re,im: Long;
- a2: Longint;
- pSave: PLongArray;
- begin
- { go through the data set and convert it to magnitude form }
- if FSaveData then
- pSave := Pointer(PChar(FSaveBuffer) + Fx2*(FFTLen div 2)*sizeof(Long))
- else
- pSave := nil;
- if not FLogAmp then
- begin
- { Use sqrt(a2) in linear-amplitude mode }
- for i := 0 to (FFTLen div 2)-1 do
- begin
- if MagnitudeForm then
- begin
- a2 := PLongArray(FFFTData)^[i];
- end
- else
- begin
- { Compute the magnitude }
- {$IFDEF WIN32}
- re := FFFTData^[i+i];
- im := FFFTData^[i+i+1];
- {$ELSE}
- re := FFFTData^[FFT.BitReversed^[i]];
- im := FFFTData^[FFT.BitReversed^[i]+1];
- {$ENDIF}
- a2 := re*re+im*im;
- end;
- { Watch for possible overflow }
- if a2 < 0 then a2 := 0;
- FDisplayVal^[i] := Trunc((FAmpScale*sqrt(a2))+(-90-FSensitivy))+MIN_COLOR;
- if (pSave <> nil) then
- pSave[i] := FDisplayVal^[i];
- end;
- end
- else
- begin { log-amplitude mode }
- for i := 0 to (FFTLen div 2)-1 do
- begin
- if MagnitudeForm then
- begin
- a2 := PLongArray(FFFTData)^[i];
- end
- else
- begin
- { Compute the magnitude }
- {$IFDEF WIN32}
- re := FFFTData^[i+i];
- im := FFFTData^[i+i+1];
- {$ELSE}
- re := FFFTData^[FFT.BitReversed^[i]];
- im := FFFTData^[FFT.BitReversed^[i]+1];
- {$ENDIF}
- a2 := re*re+im*im;
- end;
- { Watch for possible overflow }
- if a2 < 1 then a2 := 1;
- FDisplayVal^[i] := Trunc((20*FAmpScale*Log(a2))+2*(-90-FSensitivy))+MIN_COLOR;
- if (pSave <> nil) then
- pSave[i] := FDisplayVal^[i];
- end;
- end;
- end;
- {.$DEFINE COLORTEST}
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawData(pDispData: PLongArray);
- var
- i, j, y, index, repcount: integer;
- val,val2: Long;
- oldData: PSmallInt;
- LastVal: integer;
- {$IFDEF COLRTEST}
- clr: integer;
- {$ENDIF}
- begin
- val := 0;
- i := 0;
- y := FHeight-1;
- oldData := Pointer(FOldData);
- LastVal := MIN_COLOR;
- repcount := 0;
- {$IFDEF COLORTEST}
- clr := MIN_COLOR+NUM_COLORS;
- {$ENDIF}
- while i < FHeight do
- begin
- { If this line is the same as the previous one, just use the previous
- Y value. Else go ahead and compute the value. }
- index := Fy1^[i];
- if (index <> -1) or (i = FHeight-1) then
- begin
- if i > 0 then
- begin
- if (FEmbossed) then
- begin
- { Get difference with offset }
- val2 := OldData^ - val + (NUM_COLORS div 2);
- Olddata^ := LastVal;
- inc(OldData);
- LastVal := val;
- val := val2;
- end;
- val := MinMax(val,MIN_COLOR,MIN_COLOR+NUM_COLORS-1);
- for j := 0 to repcount-1 do
- begin
- if y >= 0 then FColorValues^[y] := val;
- dec(y);
- end;
- if (i = FHeight-1) then
- begin
- while y > -1 do
- begin
- FColorValues^[y] := val;
- dec(y);
- end;
- break;
- end;
- end;
- repcount := 0;
- {$IFDEF COLORTEST}
- dec(Clr);
- val:= Clr;
- {$ELSE}
- val := pDispData^[index];
- if (Fy2^[i] > 0) then { Take the maximum of a set of bins }
- begin
- while (index < Fy2^[i]) do
- begin
- if (pDispData^[index] > val) then
- val := pDispData^[index];
- inc(index);
- end;
- end;
- {$ENDIF}
- end;
- inc(repcount);
- inc(i);
- end;
- DIBCanvas.DIB_VLineMultiColor(Fx1, 0, PByte(FColorValues), FHeight);
- { for i := 0 to FHeight-1 do DIBCanvas.DIB_SetPixel(Fx1,i,FColorValues^[i]);}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetFrequency(Pos: TPoint): Float;
- begin
- Result := 0;
- if PtInRect(FClientRect,Pos) then
- begin
- dec(Pos.Y,FClientRect.Top);
- Result := FFreqBase+(FSampleRate/2-FFreqScaleFactor*FFReqBase)*(FHeight-Pos.Y-1)/(FHeight-1)/FFreqScaleFactor;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.CalcScaleSteps;
- begin
- { calc the number of steps required }
- FNumScaleSteps := Trunc(FSampleRate/2/1000*FFreqScaleFactor);
- while (FHeight div FNumScaleSteps < SCALEFONTSIZE) do
- begin
- FNumScaleSteps := FNumScaleSteps div 2;
- if FNumScaleSteps <= 1 then break;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.GetScaleBackColor: TColor;
- begin
- {$IFNDEF BUILD_ACTIVEX}
- Result := TForm(Parent).Color;
- {$ELSE}
- Result := FScaleBackColor;
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawFrequencyScale;
- var
- aBitmap: TBitmap;
- i, X, Y: integer;
- Text: String;
- Step: Float;
- begin
- { put up the frequency scale }
- if FDrawScale then
- begin
- aBitmap := TBitmap.Create;
- try
- aBitmap.Width := SCALEWIDTH;
- aBitmap.Height := Height;
- aBitmap.Canvas.Font.Color := FScaleTextColor;
- aBitmap.Canvas.Pen.Color := FScaleLineColor;
- aBitmap.Canvas.Brush.Color := GetScaleBackColor;
- with aBitmap.Canvas do
- begin
- { Put up the frequency scale. }
- Step := (FSampleRate/2-FFreqScaleFactor*FFReqBase)/FNumScaleSteps/FFreqScaleFactor/1000;
- { draw the left side }
- FillRect(Rect(0,0,aBitmap.Width,aBitmap.Height));
- X := SCALEWIDTH-1;
- MoveTo(X, Height-BevelExtend-1);
- for i := 0 to FNumScaleSteps do
- begin
- Y := Height - BevelExtend - Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
- LineTo(X, Y);
- LineTo(X-3, Y);
- MoveTo(X, Y);
- if (FFreqBase > 0) or (FFreqScaleFactor > 1) then
- Text := Format('%4.2f',[FFreqBase/1000+i*step])
- else
- Text := IntToStr(Round(FFreqBase/1000+i*step-0.05));
- TextOutAligned(aBitmap.Canvas, X-5, Y, Text,SCALEFONT,SCALEFONTSIZE,1);{ right text }
- end;
- { write right scale text }
- if (FFreqBase = 0) and (FFreqScaleFactor = 1) then
- TextOutAligned(aBitmap.Canvas, 2, Height-5,
- 'KHz', SCALEFONT,SCALEFONTSIZE,0);
- { copy to screen }
- Canvas.Draw(-3, 0, aBitmap);
- { draw the right side }
- FillRect(Rect(0,0,aBitmap.Width,aBitmap.Height));
- X := 0;
- MoveTo(X, Height-BevelExtend-1);
- for i := 0 to FNumScaleSteps do
- begin
- Y := Height - BevelExtend - Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
- LineTo(X, Y);
- LineTo(X+3, Y);
- MoveTo(X, Y);
- if (FFreqBase > 0) or (FFreqScaleFactor > 1) then
- Text := Format('%4.2f',[FFreqBase/1000+i*step])
- else
- Text := IntToStr(Round(FFreqBase/1000+i*step-0.05));
- TextOutAligned(aBitmap.Canvas, X+6, Y, Text, SCALEFONT,SCALEFONTSIZE,0);{ left text }
- end;
- { write right scale text }
- if (FFreqBase = 0) and (FFreqScaleFactor = 1) then
- TextOutAligned(aBitmap.Canvas, SCALEWIDTH-19, Height-5,
- 'KHz', SCALEFONT,SCALEFONTSIZE,0);
- { copy to screen }
- Canvas.Draw((Width - SCALEWIDTH)+3, 0, aBitmap);
- end;
- finally
- aBitmap.Free;
- end;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawBar;
- var
- i,Y: integer;
- aRect: TRect;
- begin
- if (FBarWidth > 0) then
- begin
- if FAccelerate then
- with Canvas do
- begin
- Pen.Mode := pmCopy;
- Pen.Color := FBarColor;
- Pen.Width := 1;
- aRect := Rect(FClientRect.Left+Fx2,FClientRect.Top,
- FClientRect.Left+Fx2,FClientRect.Bottom);
- MoveTo(aRect.Left, aRect.Top);
- LineTo(aRect.Left, aRect.Bottom);
- for i := 0 to FNumScaleSteps do
- begin
- Y := (BevelExtend+FHeight)-Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
- SetPixel(Handle,aRect.Left, Y, FBarTickColor);
- end;
- end
- else
- with DIBCanvas do
- begin
- Pen.Mode := pmCopy;
- Brush.Color := FBarColor;
- if Fx2 > Fx1 then
- begin
- aRect := Rect(Fx1+1,0,Fx2+1,FHeight);
- FillRect(aRect);
- end
- else
- begin
- aRect := Rect(0,0,Fx2+1,FHeight);
- FillRect(aRect);
- end;
- Pen.Color := FBarTickColor;
- for i := 0 to FNumScaleSteps do
- begin
- Y := FHeight - Trunc(i * (FHeight-1)/FNumScaleSteps)-1;
- MoveTo(aRect.Left,Y);
- LineTo(aRect.Right,Y);
- end;
- end;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawSelection(aCanvas: TMMDIBCanvas; sStart, sEnd: Longint;
- sColor: TColor; Solid: Boolean);
- var
- rColor: Longint;
- begin
- if (sStart >= 0) and (sEnd >= 0) then
- begin
- with aCanvas do
- begin
- DIB_SetTColor(sColor);
- if Solid then
- begin
- DIB_FillRectXor(Rect(sStart,0,sEnd+1,Height));
- end
- else
- begin
- DIB_SetTColor(sColor);
- DIB_HLineDashed(sStart,sEnd+1,0);
- DIB_HLineDashed(sStart,sEnd+1,Height-1);
- DIB_VLineDashed(sStart,0,Height-1);
- DIB_VLineDashed(sEnd,0,Height-1);
- end;
- end;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawLocator(aCanvas: TMMDIBCanvas; aPos: Longint; aColor: TColor);
- begin
- with aCanvas do
- begin
- DIB_SetTColor(aColor);
- DIB_MoveTo(aPos,0);
- DIB_LineTo(aPos,FHeight);
- end;
- end;
- {$IFDEF WIN32}
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawInfo(Pos: TPoint);
- var
- Text: String;
- aRect: TRect;
- Buf: array[0..255] of Char;
- DC: HDC;
- WindowHandle: HWND;
- begin
- if FShowInfoHint then
- with DIBCanvas do
- begin
- if PtInRect(FClientRect,Pos) then
- begin
- Text := Format('%2.3f KHz', [GetFrequency(Pos)/1000]);
- Font.Name := 'MS Sans Serif';
- Font.Size := 8;
- Font.Style := [];
- {$IFDEF WIN32}
- Font.Color := clInfoText;
- {$ELSE}
- Font.Color := clBlack;
- {$ENDIF}
- aRect.Left := Pos.X-BevelExtend;
- if FDrawScale then dec(aRect.Left, SCALEWIDTH);
- aRect.Top := Pos.Y-BevelExtend+15;
- aRect.Right := aRect.Left + TextWidth(Text)+4;
- aRect.Bottom := aRect.Top + TextHeight(Text)+2;
- if (aRect.Bottom > FHeight) then OffsetRect(aRect,0,-40);
- if (aRect.Right > FWidth) then OffsetRect(aRect,FWidth-aRect.Right,0);
- if (aRect.Top < 0) then
- begin
- aRect.Top := 0;
- aRect.Bottom := TextHeight(Text)+2;
- end;
- {$IFDEF TRIAL}
- {$DEFINE _HACK3}
- {$I MMHACK.INC}
- {$ENDIF}
- if (SaveDC = 0) then
- begin
- { create memory DC for save bitmap }
- SaveDC := CreateCompatibleDC(DIBCanvas.Handle);
- { create bitmap to store background }
- SaveWidth := 10*TextWidth('W')+4;
- SaveHeight := TextHeight('W')+2;
- SaveBitmap := CreateCompatibleBitmap(DIBCanvas.Handle,SaveWidth,SaveHeight);
- OldBitmap := SelectObject(SaveDC, SaveBitmap);
- OldPalette := SelectPalette(SaveDC, DIBCanvas.Palette, False);
- end
- else
- { restore background }
- BitBlt(DIBCanvas.Handle,SaveInfoPos.X,
- SaveInfoPos.Y,SaveWidth,SaveHeight,
- SaveDC, 0,0,SRCCOPY);
- { save background }
- BitBlt(SaveDC,0,0,SaveWidth,SaveHeight,
- DIBCanvas.Handle,aRect.Left,aRect.Top,SRCCOPY);
- SaveInfoPos := aRect.TopLeft;
- Brush.Color := INFOCOLOR;
- Brush.Style := bsSolid;
- Pen.Color := clBlack;
- Rectangle(aRect.Left,aRect.Top,aRect.Right,aRect.Bottom);
- Brush.Style := bsClear;
- DrawText(Handle, StrPCopy(Buf, Text), -1, aRect,
- DT_SINGLELINE or DT_VCENTER or DT_CENTER or DT_NOPREFIX);
- Brush.Style := bsSolid;
- end
- else if (SaveDC <> 0) then
- begin
- { restore background }
- BitBlt(DIBCanvas.Handle,SaveInfoPos.X,
- SaveInfoPos.Y,SaveWidth,SaveHeight,
- SaveDC,0,0,SRCCOPY);
- end;
- DIB_InitDrawing; { copy to screen }
- DC := GetDeviceContext(WindowHandle);
- DIBCanvas.DIB_BitBlt(DC, FClientRect,0,0);
- ReleaseDC(WindowHandle, DC);
- DIB_DoneDrawing;
- end;
- end;
- {$ELSE}
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawInfo(Pos: TPoint);
- var
- Text: String;
- aRect: TRect;
- Buf: array[0..255] of Char;
- Border: integer;
- begin
- if FShowInfoHint then
- with Canvas do
- begin
- if PtInRect(FClientRect,Pos) then
- begin
- Text := Format('%2.3f KHz', [GetFrequency(Pos)/1000]);
- Font.Name := 'MS Sans Serif';
- Font.Size := 8;
- Font.Style := [];
- {$IFDEF WIN32}
- Font.Color := clInfoText;
- {$ELSE}
- Font.Color := clBlack;
- {$ENDIF}
- aRect.Left := Pos.X;
- aRect.Top := Pos.Y+15;
- aRect.Right := aRect.Left + TextWidth(Text)+4;
- aRect.Bottom := aRect.Top + TextHeight(Text)+2;
- if (aRect.Bottom > Height-BevelExtend) then OffsetRect(aRect,0,-40);
- Border := BevelExtend;
- if FDrawScale then inc(Border,SCALEWIDTH);
- if (aRect.Right > Width-Border) then
- OffsetRect(aRect,Width-Border-aRect.Right,0);
- if (aRect.Top < 0) then
- begin
- aRect.Top := 0;
- aRect.Bottom := TextHeight(Text)+2;
- end;
- if (SaveDC = 0) then
- begin
- { create memory DC for save bitmap }
- SaveDC := CreateCompatibleDC(Canvas.Handle);
- { create bitmap to store background }
- SaveWidth := 10*TextWidth('W')+4;
- SaveHeight := TextHeight('W')+2;
- SaveBitmap := CreateCompatibleBitmap(Canvas.Handle,SaveWidth,SaveHeight);
- OldBitmap := SelectObject(SaveDC, SaveBitmap);
- OldPalette := SelectPalette(SaveDC, DIBCanvas.Palette, False);
- end
- else
- { restore background }
- BitBlt(Canvas.Handle,SaveInfoPos.X,
- SaveInfoPos.Y,SaveWidth,SaveHeight,
- SaveDC,0,0,SRCCOPY);
- { save background }
- BitBlt(SaveDC,0,0,SaveWidth,SaveHeight,
- Canvas.Handle,aRect.Left,aRect.Top,SRCCOPY);
- SaveInfoPos := aRect.TopLeft;
- Brush.Color := INFOCOLOR;
- Brush.Style := bsSolid;
- Pen.Color := clBlack;
- Rectangle(aRect.Left,aRect.Top,aRect.Right,aRect.Bottom);
- Brush.Style := bsClear;
- DrawText(Handle, StrPCopy(Buf, Text), -1, aRect,
- DT_SINGLELINE or DT_VCENTER or DT_CENTER or DT_NOPREFIX);
- Brush.Style := bsSolid;
- end
- else if (SaveDC <> 0) then
- begin
- { restore background }
- BitBlt(Canvas.Handle,SaveInfoPos.X,
- SaveInfoPos.Y,SaveWidth,SaveHeight,
- SaveDC,0,0,SRCCOPY);
- end;
- end;
- end;
- {$ENDIF}
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.DrawSpectrogram(ClearBackGround: Boolean);
- var
- i: integer;
- aRect: TRect;
- begin
- // ClearBackGround := False;
- // FNeedReset := False;
- DIBCanvas.DIB_InitDrawing;
- { clear background }
- if ClearBackGround or FNeedReset then
- begin
- if FEmbossed then
- DIBCanvas.DIB_SetColor((MIN_COLOR+NUM_COLORS) div 2)
- else
- DIBCanvas.DIB_SetColor(MIN_COLOR);
- DIBCanvas.DIB_Clear;
- Fx1 := -FBarWidth;//Max(-FBarWidth,0);
- Fx2 := 0;
- if ClearBackGround and FSaveData then
- begin
- //DB_WriteStrLn(0,'Restoring Data...');
- for i := 0 to FWidth-1 do
- begin
- DrawData(Pointer(PChar(FSaveBuffer) + Fx2*(FFTLen div 2)*sizeof(Long)));
- inc(Fx1);
- if (Fx1 = FWidth) then Fx1 := 0;
- inc(Fx2);
- if (Fx2 = FWidth) then Fx2 := 0;
- end;
- end;
- if not FNeedReset and not FSaveData then
- ResetSpectrograms(Self);
- end
- else
- begin
- { now plot the data }
- DrawData(FDisplayVal);
- end;
- { copy to screen }
- if ClearBackGround or FNeedReset {or FSaveData} or not FAccelerate then
- begin
- if not FScroll or (Fx2 < FWidth) then DrawBar;
- { draw solid Selection }
- DrawSelection(DIBCanvas,FSelectStart,FSelectEnd,FSelectColor,True);
- { draw doted Selection }
- DrawSelection(DIBCanvas,FSelectStart,FSelectEnd,FSelectDotColor,False);
- { draw the locator }
- DrawLocator(DIBCanvas,FLocator,FLocatorColor);
- DIBCanvas.DIB_BitBlt(Canvas.Handle, FClientRect,0,0);
- FNeedReset := False;
- end
- else
- begin
- aRect := FClientRect;
- aRect.Left := FClientRect.Left + Fx1;
- aRect.Right := 1;
- DIBCanvas.DIB_BitBlt(Canvas.Handle,aRect,Fx1,0);
- end;
- { move the bar }
- if FScroll then
- begin
- if (Fx2 < FWidth) then
- begin
- if Accelerate then DrawBar;
- inc(Fx1);
- inc(Fx2);
- end
- else
- begin
- if Accelerate then
- begin
- {$IFNDEF BUILD_ACTIVEX}
- aRect:= BoundsRect;
- {$ELSE}
- aRect:= ClientRect;
- {$ENDIf}
- InflateRect(aRect, -BevelExtend, -BevelExtend);
- if FDrawScale then InflateRect(aRect, -SCALEWIDTH, 0);
- dec(aRect.Right,Max(FBarWidth-1,0));
- {$IFNDEF BUILD_ACTIVEX}
- ScrollWindowEx(Parent.Handle,-1,0,@aRect,@aRect,0,nil,0);
- {$ELSE}
- ScrollWindowEx(Handle,-1,0,@aRect,@aRect,0,nil,0);
- {$ENDIF}
- end
- else DIBCanvas.DIB_CopyDIBBits(biSurface,0,0,FWidth-1,FHeight,1,0);
- end;
- end
- else if not FSaveData or not ClearBackGround then
- begin
- if FAccelerate then DrawBar;
- inc(Fx1);
- if (Fx1 = FWidth) then Fx1 := 0;
- inc(Fx2);
- if (Fx2 = FWidth) then Fx2 := 0;
- end;
- DIBCanvas.DIB_DoneDrawing;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- Procedure TMMSpectrogram.Paint;
- var
- aRect: TRect;
- begin
- with Canvas do
- begin
- if FDrawScale then
- begin
- { clear the space between the scales only, to eliminate flicker }
- Brush.Color := GetScaleBackColor;
- Brush.Style := bsSolid;
- aRect := Rect(0,0,SCALEWIDTH,Height);
- aRect := Rect(SCALEWIDTH-3,0,SCALEWIDTH,Height);
- FillRect(aRect);
- aRect:= Rect(Width-SCALEWIDTH,0,Width-SCALEWIDTH+3,Height);
- FillRect(aRect);
- { make place for the scale }
- aRect := GetClientRect;
- InflateRect(aRect,-SCALEWIDTH,0);
- end
- else aRect := GetClientRect;
- { draw the Bevel }
- aRect := Bevel.PaintBevel(Canvas, aRect, True);
- end;
- { now draw the scales and the spectrogram }
- DrawFrequencyScale;
- if (csDesigning in ComponentState) {$IFDEF WIN32}or (csPaintCopy in ControlState){$ENDIF} then
- DrawSpectrogram(True)
- else
- FastDraw(DrawSpectrogram,True);
- {$IFDEF BUILD_ACTIVEX}
- if Selected then
- begin
- Canvas.Brush.Style := bsClear;
- Canvas.Pen.Color := clRed;
- Canvas.Rectangle(0,0,Width,Height);
- Canvas.Brush.Style := bsSolid;
- end;
- {$ENDIF}
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.Selecting(Min, Max: Longint);
- begin
- Select(Min,Max,True);
- if assigned(FOnSelecting) then FOnSelecting(Self,Min,Max);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.SelectEnd(Min, Max: Longint);
- begin
- Select(Min,Max,False);
- if assigned(FOnSelectEnd)then FOnSelectEnd(Self,Min,Max);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.IsLocator(X: integer): Boolean;
- begin
- Result := (FLocator >= 0) and
- (X >= (FLocator+BevelExtend)-3) and
- (X <= (FLocator+BevelExtend)+3) and
- (X >= 0) and (X <= Width);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.IsSelectStart(X: integer): Boolean;
- begin
- Result := (FSelectStart >= 0) and
- (X >= (FSelectStart+BevelExtend)-3) and
- (X <= (FSelectStart+BevelExtend)+2) and
- (X >= 0) and (X <= Width);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.IsSelectEnd(X: integer): Boolean;
- begin
- Result := (FSelectEnd >= 0) and
- (X >= (FSelectEnd+BevelExtend)-2) and
- (X <= (FSelectEnd+BevelExtend)+3) and
- (X >= 0) and (X <= Width);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- function TMMSpectrogram.IsInSelection(X: integer): Boolean;
- begin
- Result := (FSelectStart >= 0) and (FSelectEnd >= 0) and
- (X >= (FSelectStart+BevelExtend)) and
- (X <= (FSelectEnd+BevelExtend)) and
- (X >= 0) and (X <= Width);
- end;
- var
- StartOrigin,Origin,
- MinShift,
- MaxShift: Longint;
- Moving : Boolean;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- aRect: TRect;
- begin
- if not (csDesigning in ComponentState) and Enabled then
- begin
- if (Button = mbLeft) and FShowInfo then
- begin
- aRect.TopLeft := ClientToScreen(FClientRect.TopLeft);
- aRect.BottomRight := ClientToScreen(FClientRect.BottomRight);
- ClipCursor(@aRect);
- FShowInfoHint := True;
- { maybe there is a hint, hide it }
- if ShowHint then
- begin
- FOldShowHint := ShowHint;
- ShowHint := False;
- Application.CancelHint;
- Update;
- end
- else FOldShowHint := False;
- {$IFDEF WIN32}
- { we must save the screen in our bitmap }
- DIBCanvas.CopyRect(Rect(0,0,FWidth,FHeight),Canvas,FClientRect);
- {$ENDIF}
- DrawInfo(Point(X,Y));
- end
- else if (Button = mbRight) and FUseSelection and not FLocked and not FDrawing then
- begin
- aRect := BeveledRect;
- if PtInRect(aRect,Point(X,Y)) then
- begin
- FDrawing := True;
- Moving := False;
- MouseCapture := True;
- if IsSelectStart(X) then
- begin
- Origin := FSelectEnd;
- end
- else if IsSelectEnd(X) then
- begin
- Origin := FSelectStart;
- end
- else if IsInSelection(X) then
- begin
- Windows.SetCursor(Screen.Cursors[crsHand4]);
- Moving := True;
- Origin := X-BevelExtend;
- MinShift := -(FSelectStart);
- MaxShift := (FWidth-1)-FSelectEnd;
- end
- else
- begin
- Windows.SetCursor(Screen.Cursors[crSizeWE]);
- Origin := X-BevelExtend;
- { clear old selection }
- Selecting(-1,-1);
- Selecting(Origin,Origin+1);
- end;
- StartOrigin := Origin;
- end;
- end;
- end;
- inherited MouseDown(Button, Shift, X, Y);
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.MouseMove(Shift: TShiftState; X, Y: Integer);
- var
- NewPos,Diff: Longint;
- begin
- if FShowInfo and FShowInfoHint then
- begin
- inherited MouseMove(Shift, X, Y);
- DrawInfo(Point(X,Y));
- end
- else if FUseSelection and not FLocked and FDrawing then
- begin
- X := Limit(X,BevelExtend,(Width-BevelExtend)-1);
- if Moving then
- begin
- Diff := Limit((X-BevelExtend)-Origin,MinShift,MaxShift);
- Selecting(FSelectStart+Diff,FSelectEnd+Diff);
- Origin := Origin + Diff;
- MinShift := MinShift - Diff;
- MaxShift := MaxShift - Diff;
- end
- else
- begin
- NewPos := Limit(X-BevelExtend,0,Width-2*BevelExtend);
- Selecting(Origin,NewPos);
- end;
- inherited MouseMove(Shift, X, Y);
- end
- else if FUseSelection and not FLocked then
- begin
- inherited MouseMove(Shift, X, Y);
- if IsSelectStart(X) or IsSelectEnd(X) then
- Cursor := crSizeWE
- else if IsInSelection(X) then
- Cursor := crsHand3
- else if (Cursor=crSizeWE)or(Cursor=crsHand3)or(Cursor=crsZoom1) then
- Cursor := crDefault;
- end
- else
- begin
- inherited MouseMove(Shift, X, Y);
- if (Cursor <> crCross) and (Cursor <> crHourGlass) then
- Cursor := crDefault;
- end;
- end;
- {-- TMMSpectrogram ------------------------------------------------------}
- procedure TMMSpectrogram.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- P: TPoint;
- begin
- if (Button = mbLeft) and FShowInfoHint then
- begin
- { restore background }
- if FEnabled then DrawInfo(Point(-1,-1));
- if (SaveDC <> 0) then
- begin
- SelectObject(SaveDC, OldBitmap);
- DeleteObject(SaveBitmap);
- SelectObject(SaveDC, OldPalette);
- SaveBitmap := 0;
- DeleteDC(SaveDC);
- SaveDC := 0;
- end;
- FShowInfoHint := False;
- ClipCursor(nil);
- ShowHint := FOldShowHint;
- end
- else if (Button = mbRight) and FDrawing then
- begin
- FDrawing := False;
- MouseCapture := False;
- if (FSelectEnd = FSelectStart+1) or (FSelectEnd = FSelectStart-1) then
- begin
- Selecting(-1,-1);
- end;
- SelectEnd(FSelectStart,FSelectEnd);
- end;
- inherited MouseUp(Button, Shift, X, Y);
- end;
- end.