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

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 10.01.99 - 15:45:43 $                                        =}
  24. {========================================================================}
  25. Unit MMLevel;
  26. {$C FIXED PRELOAD PERMANENT}
  27. {$I COMPILER.INC}
  28. Interface
  29. Uses
  30. {$IFDEF WIN32}
  31.     Windows,
  32. {$ELSE}
  33.     WinTypes,
  34.     WinProcs,
  35. {$ENDIF}
  36.     SysUtils,
  37.     Messages,
  38.     Classes,
  39.     Graphics,
  40.     Controls,
  41.     Forms,
  42.     Dialogs,
  43.     Menus,
  44.     MMSystem,
  45.     MMUtils,
  46.     MMString,
  47.     MMObj,
  48.     MMTimer,
  49.     MMMulDiv,
  50.     MMMath,
  51.     MMRegs,
  52.     MMPCMSup,
  53.     MMWaveIO,
  54.     MMDIBCv,
  55.     MMScale;
  56. const
  57.     {$IFDEF CBUILDER3} {$EXTERNALSYM MAXDECAYCOUNT} {$ENDIF}
  58.     MAXDECAYCOUNT   = 32;  { Maximum amount of temporal averaging allowed }
  59.     {$IFDEF CBUILDER3} {$EXTERNALSYM VALUERANGE} {$ENDIF}
  60.     VALUERANGE      = 100; { Range for SetValue/GetValue, here 0..100%    }
  61.     SYNCBARS : integer = 2;
  62. type
  63.     EMMLevelError     = class(Exception);
  64.     TMMLevelKind      = (lkHorizontal, lkVertical);
  65.     TMMLevelDirection = (dirNormal, dirReversed,dirSymetric);
  66.     TMMLevelDrawBar   = procedure(Sender: TObject; DIB: TMMDIBCanvas;
  67.                                   Rect: TRect; nSpots, Peak: integer) of object;
  68.     { array for uniform decay mode values }
  69.     TDataBuf  = array[0..MAXDECAYCOUNT-1] of Long;
  70.     {-- TMMCustomLevel ---------------------------------------------------------}
  71.     TMMCustomLevel = class(TMMDIBGraphicControl)
  72.     private
  73.       FTimerID      : Longint;      { timer for peak handling              }
  74.       FBarDIB       : TMMDIBCanvas; { bitmap for inactive spots            }
  75.       FEnabled      : Boolean;      { Enable or disable Level              }
  76.       FKind         : TMMLevelKind; { draw horizontal / vertikal bars      }
  77.       FBar1Color    : TColor;       { Farbe f黵 die Punkte im 1. Abschnitt }
  78.       FBar2Color    : TColor;       { Farbe f黵 die Punkte im 2. Abschnitt }
  79.       FBar3Color    : TColor;       { Farbe f黵 die Punkte im 3. Abschnitt }
  80.       FInact1Color  : TColor;       { foreColor for inactive spots 1       }
  81.       FInact2Color  : TColor;       { foreColor for inactive spots 2       }
  82.       FInact3Color  : TColor;       { foreColor for inactive spots 3       }
  83.       FInactiveDoted: Boolean;      { draw the inactive spots doted        }
  84.       FActiveDoted  : Boolean;      { draw the active spots doted          }
  85.       FPoint1       : integer;      { Schwelle von 1. zu 2. Abschnitt %    }
  86.       FPoint2       : integer;      { Schwelle von 2. zu 3. Abschnitt %    }
  87.       FPoint1Spot   : integer;      { on which spot begins next color      }
  88.       FPoint2Spot   : integer;      { on which spot begins next color      }
  89.       FSpotSpace    : integer;      { Horizontal space between spots       }
  90.       FSpotWidth    : integer;      { the spot width in pixel              }
  91.       FFirstSpace   : integer;      { the space before the first spot      }
  92.       FNumSpots     : integer;      { number of Spots                      }
  93.       FDirection    : TMMLevelDirection;{ draw direction, forward/backward }
  94.       FBits         : TMMBits;      { bit8 or bit16                        }
  95.       FChannel      : TMMChannel;   { chBoth, chLeft or chRigth            }
  96.       FMode         : TMMMode;      { mMono or mStereo                     }
  97.       FBytes        : Longint;      { calculated data bytes per level      }
  98.       FGain         : Integer;      { the linear gain for the pcm data     }
  99.       FSamples      : integer;      { number of samples for calculation    }
  100.       FSensitivy    : integer;      { here starts the display (db) scaling }
  101.       FLogAmp       : Boolean;      { set to True for log-based amp. scale }
  102.       FData         : integer;      { the current data for the level       }
  103.       FDataBuf      : TDataBuf;     { Memory for averaging mode            }
  104.       FDecay        : integer;      { the current Decay value              }
  105.       FDecayMode    : TMMDecayMode; { indicating decay mode on/off         }
  106.       FDecayFactor  : Float;        { Geometric decay factor               }
  107.       FDecayCount   : integer;      { Temporal averaging parameter         }
  108.       FDecayCntAct  : integer;      { Total num of bins averaged so far    }
  109.       FDecayPtr     : integer;      { Index for averaging buffer location  }
  110.       FLastVal_F    : Float;        { Lastvalue for exp decay mode         }
  111.       FLastVal      : Longint;      { Lastvalue for uniform averaging      }
  112.       FNumPeaks     : integer;      { number of spots displayed as peak    }
  113.       FDrawScale    : Boolean;      { draw the scale or not                }
  114.       FCurPeak      : integer;      { the actual sample Peak Value         }
  115.       FPeak         : integer;      { the actual Peak Value for the display}
  116.       FPeakDelay    : integer;      { the delay for the peak spot          }
  117.       FPeakSpeed    : integer;      { the decrease speed for the peak spot }
  118.       FPeakCounter  : integer;      { internal Peak delay counter          }
  119.       FWidth        : integer;      { calculated width without border      }
  120.       FHeight       : integer;      { calculated height without border     }
  121.       FClientRect   : TRect;        { calculated beveled Rect              }
  122.       FRange        : Longint;      { pcm input dynamic range              }
  123.       FRefresh      : Boolean;      { needs the peak a refresh ?           }
  124.       FDCOffsetL    : integer;
  125.       FDCOffsetR    : integer;
  126.       FDrawReversed : Boolean;
  127.       { Events }
  128.       FOnPaint       : TNotifyEvent;
  129.       FOnGainOverflow: TNotifyEvent;
  130.       FOnPcmOverflow : TNotifyEvent;
  131.       FOnDrawBar     : TMMLevelDrawBar;
  132.       procedure ResetDecayBuffers;
  133.       procedure CalcNumSpots;
  134.       procedure SetBytesPerLevel;
  135.       procedure DrawInactiveSpots;
  136.       procedure DrawLevelHorizontal(DIB: TMMDIBCanvas; nSpots, Peak: integer; DrawAll: Boolean);
  137.       procedure DrawLevelVertical(DIB: TMMDIBCanvas; nSpots, Peak: integer; DrawAll: Boolean);
  138.       procedure DrawLevel(Dummy: Boolean);
  139.       procedure SetOnDrawBar(aValue: TMMLevelDrawBar);
  140.       procedure SetEnabled(aValue: Boolean);
  141.       procedure SetKind(aValue: TMMLevelKind);
  142.       Procedure SetColors(Index: Integer; aValue: TColor);
  143.       procedure SetPoints(Index, aValue: integer);
  144.       procedure SetSpotSpace(aValue: integer);
  145.       procedure SetSpotWidth(aValue: integer);
  146.       procedure SetDirection(aValue: TMMLevelDirection);
  147.       procedure SetPCMWaveFormat(wf: TPCMWaveFormat);
  148.       function  GetPCMWaveFormat: TPCMWaveFormat;
  149.       procedure SetBits(aValue: TMMBits);
  150.       procedure SetChannel(aValue: TMMChannel);
  151.       procedure SetMode(aValue: TMMMode);
  152.       procedure SetGain(aValue: Integer);
  153.       function  GetGain: integer;
  154.       procedure SetSamples(aValue: integer);
  155.       procedure SetDecayMode(aValue: TMMDecayMode);
  156.       procedure SetDecay(aValue: integer);
  157.       procedure SetNumPeaks(aValue: integer);
  158.       procedure SetPeakDelay(aValue: integer);
  159.       procedure SetPeakSpeed(aValue: integer);
  160.       procedure SetInactiveDoted(aValue: Boolean);
  161.       procedure SetActiveDoted(aValue: Boolean);
  162.       procedure SetSensitivy(aValue: integer);
  163.       procedure SetLogAmp(aValue: Boolean);
  164.       procedure SetValue(aValue: integer);
  165.       function  GetValue: integer;
  166.       function  GetPeak: integer;
  167.       function  GetPeakValue: integer;
  168.       procedure SetDCOffset(Index, aValue: integer);
  169.       function  GetDCOffset(Index: integer): integer;
  170.       procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  171.     protected
  172.       procedure SetBPP(aValue: integer); override;
  173.       procedure Paint; override;
  174.       procedure Loaded; override;
  175.       procedure GainOverflow; dynamic;
  176.       procedure PcmOverflow; dynamic;
  177.       procedure Changed; override;
  178.     public
  179.       constructor Create(AOwner: TComponent); override;
  180.       destructor  Destroy; override;
  181.       procedure   ChangeDesigning(aValue: Boolean); override;
  182.       procedure   SetBounds(aLeft, aTop, aWidth, aHeight: integer); override;
  183.       property    DrawReversed: Boolean read FDrawReversed write FDrawReversed;
  184.       procedure   RefreshPCMData(PCMData: Pointer);
  185.       procedure   SetData(SampleValue: integer);
  186.       procedure   ResetData;
  187.       property    BytesPerLevel: Longint read FBytes;
  188.       property    PCMWaveFormat: TPCMWaveFormat read GetPCMWaveFormat write SetPCMWaveFormat;
  189.       property    NumSpots: integer read FNumSpots;
  190.       property    Point1Spot: integer read FPoint1Spot;
  191.       property    Point2Spot: integer read FPoint2Spot;
  192.       property    Peak: integer read FCurPeak;
  193.       property    PeakDisplay: integer read GetPeak;
  194.       property    PeakValue: integer read GetPeakValue;
  195.     protected
  196.       { Events }
  197.       property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  198.       property OnDrawBar: TMMLevelDrawBar read FOnDrawBar write SetOnDrawBar;
  199.       property OnGainOverflow: TNotifyEvent read FOnGainOverflow write FOnGainOverflow;
  200.       property OnPcmOverflow: TNotifyEvent read FOnPcmOverflow write FOnPcmOverflow;
  201.       property ParentColor default False;
  202.       property Color default clBlack;
  203.       property Height default 17;
  204.       property Width default 200;
  205.       property Enabled: Boolean read FEnabled write SetEnabled default True;
  206.       property Kind: TMMLevelKind read FKind write SetKind default lkHorizontal;
  207.       property SpotSpace: integer read FSpotSpace write SetSpotSpace default 1;
  208.       property SpotWidth: integer read FSpotWidth write SetSpotWidth default 1;
  209.       property Bar1Color: TColor index 0 read FBar1Color write SetColors default clAqua;
  210.       property Bar2Color: TColor index 1 read FBar2Color write SetColors default clAqua;
  211.       property Bar3Color: TColor index 2 read FBar3Color write SetColors default clRed;
  212.       property Inactive1Color: TColor index 3 read FInact1Color write SetColors default clTeal;
  213.       property Inactive2Color: TColor index 4 read FInact2Color write SetColors default clTeal;
  214.       property Inactive3Color: TColor index 5 read FInact3Color write SetColors default clMaroon;
  215.       property InactiveDoted: Boolean read FInactiveDoted write SetInactiveDoted default False;
  216.       property ActiveDoted: Boolean read FActiveDoted write SetActiveDoted default False;
  217.       property Point1: integer index 0 Read FPoint1 write SetPoints default 50;
  218.       property Point2: integer index 1 Read FPoint2 write SetPoints default 85;
  219.       property Direction: TMMLevelDirection read FDirection write SetDirection default dirNormal;
  220.       property BitLength: TMMBits read FBits write setBits default b8bit;
  221.       property Channel: TMMChannel read FChannel write setChannel default chBoth;
  222.       property Mode: TMMMode read FMode write SetMode default mMono;
  223.       property Gain: Integer read getGain write setGain default 0;
  224.       property Samples: integer read FSamples write SetSamples default 50;
  225.       property Sensitivy: integer read FSensitivy write SetSensitivy default -35;
  226.       property LogAmp: Boolean read FLogAmp write SetLogAmp default True;
  227.       property NumPeaks: integer read FNumPeaks write SetNumPeaks default 1;
  228.       property PeakDelay: integer read FPeakDelay write SetPeakDelay default 20;
  229.       property PeakSpeed: integer read FPeakSpeed write SetPeakSpeed default 0;
  230.       property DecayMode: TMMDecayMode read FDecayMode write SetDecayMode default dmNone;
  231.       property Decay: integer read FDecay write SetDecay default 1;
  232.       property Value: integer read GetValue write SetValue stored False default 0;
  233.       property DCOffsetL: integer index 0 read GetDCOffset write SetDCOffset default 0;
  234.       property DCOffsetR: integer index 1 read GetDCOffset write SetDCOffset default 0;
  235.     end;
  236.     {-- TMMLevel --------------------------------------------------------}
  237.     TMMLevel = class(TMMCustomLevel)
  238.     published
  239.       property OnClick;
  240.       property OnDblClick;
  241.       property OnMouseDown;
  242.       property OnMouseMove;
  243.       property OnMouseUp;
  244.       property OnDrawBar;
  245.       property OnGainOverflow;
  246.       property OnPcmOverflow;
  247.       property OnPaint;
  248.       property OnDragDrop;
  249.       property OnDragOver;
  250.       property OnEndDrag;
  251.       property OnStartDrag;
  252.       property Align;
  253.       property Bevel;
  254.       property PopupMenu;
  255.       property ParentShowHint;
  256.       property ParentColor;
  257.       property ShowHint;
  258.       property Visible;
  259.       property Color;
  260.       property DragCursor;
  261.       property Enabled;
  262.       property Kind;
  263.       property Height;
  264.       property Width;
  265.       property SpotSpace;
  266.       property SpotWidth;
  267.       property Bar1Color;
  268.       property Bar2Color;
  269.       property Bar3Color;
  270.       property Inactive1Color;
  271.       property Inactive2Color;
  272.       property Inactive3Color;
  273.       property InactiveDoted;
  274.       property ActiveDoted;
  275.       property Point1;
  276.       property Point2;
  277.       property Direction;
  278.       property BitLength;
  279.       property Channel;
  280.       property Mode;
  281.       property Gain;
  282.       property Samples;
  283.       property Sensitivy;
  284.       property LogAmp;
  285.       property NumPeaks;
  286.       property PeakDelay;
  287.       property PeakSpeed;
  288.       property DecayMode;
  289.       property Decay;
  290.       property Value;
  291.       property DCOffsetL;
  292.       property DCOffsetR;
  293.     end;
  294.     {-- TMMLevScale -----------------------------------------------------}
  295.     TMMLevScale    = class(TMMCustomScale)
  296.     published
  297.         property Visible default False;
  298.         property TickCount;
  299.         property EnlargeEvery;
  300.         property Size;
  301.         property Origin;
  302.         property Connect;
  303.     end;
  304.     TMMScalePos    = (spAboveOrLeft, spBelowOrRight, spBoth);
  305.     {-- TMMLevelScale ---------------------------------------------------}
  306.     TMMLevelScale  = class(TMMGraphicControl)
  307.     private
  308.        FScaleTicks : integer;   { draw every FScaleTicks a volume string }
  309.        FPoint1     : integer;   { Schwelle von 1. zu 2. Abschnitt %      }
  310.        FPoint2     : integer;   { Schwelle von 2. zu 3. Abschnitt %      }
  311.        FScale1Color: TColor;    { Farbe f黵 die Punkte im 1. Abschnitt   }
  312.        FScale2Color: TColor;    { Farbe f黵 die Punkte im 2. Abschnitt   }
  313.        FScale3Color: TColor;    { Farbe f黵 die Punkte im 3. Abschnitt   }
  314.        FKind       : TMMLevelKind;
  315.        FDirection  : TMMLevelDirection;
  316.        FSensitivy  : integer;
  317.        FLogAmp     : Boolean;
  318.        FScale      : TMMLevScale;
  319.        FScalePos   : TMMScalePos;
  320.        procedure SetScale(Value: TMMLevScale);
  321.        procedure SetScalePos(Value: TMMScalePos);
  322.        procedure ScaleChanged(Sender: TObject);
  323.        procedure SetSensitivy(aValue: integer);
  324.        procedure SetLogAmp(aValue: Boolean);
  325.        procedure SetScaleTicks(aValue: integer);
  326.        procedure SetPoints(Index, aValue: integer);
  327.        procedure SetColors(Index: Integer; aValue: TColor);
  328.        procedure SetKind(aValue: TMMLevelKind);
  329.        procedure SetDirection(aValue: TMMLevelDirection);
  330.     public
  331.        constructor Create(AOwner: TComponent); override;
  332.        destructor  Destroy; override;
  333.        procedure Paint; override;
  334.     published
  335.        { Events }
  336.        property OnClick;
  337.        property OnDblClick;
  338.        property OnMouseDown;
  339.        property OnMouseMove;
  340.        property OnMouseUp;
  341.        property Align;
  342.        property Width default 200;
  343.        property Height default 7;
  344.        property Visible;
  345.        property Enabled;
  346.        property PopupMenu;
  347.        property ParentShowHint;
  348.        property ParentFont default False;
  349.        property Font;
  350.        property Color default clBlack;
  351.        property ScaleTicks: integer read FScaleTicks write SetScaleTicks default 8;
  352.        property Point1: integer index 0 Read FPoint1 write SetPoints default 50;
  353.        property Point2: integer index 1 Read FPoint2 write SetPoints default 85;
  354.        property Scale1Color: TColor index 0 read FScale1Color write SetColors default clWhite;
  355.        property Scale2Color: TColor index 1 read FScale2Color write SetColors default clWhite;
  356.        property Scale3Color: TColor index 2 read FScale3Color write SetColors default clRed;
  357.        property Sensitivy: integer read FSensitivy write SetSensitivy default -35;
  358.        property LogAmp: Boolean read FLogAmp write SetLogAmp default True;
  359.        property Kind: TMMLevelKind read FKind write SetKind default lkHorizontal;
  360.        property Direction: TMMLevelDirection read FDirection write SetDirection default dirNormal;
  361.        property Scale: TMMLevScale read FScale write SetScale;
  362.        property ScalePos: TMMScalePos read FScalePos write SetScalePos default spBoth;
  363.      end;
  364. implementation
  365. {------------------------------------------------------------------------}
  366. procedure TimeCallBack(uTimerID, dwUser: Longint); export;
  367. begin
  368.   if (dwUser <> 0) then
  369.   with TMMCustomLevel(dwUser) do
  370.   begin
  371.      if (FPeak > 0) then
  372.      begin
  373.         dec(FPeakCounter);
  374.         if FPeakCounter <= 0 then
  375.         begin
  376.            if (FPeakSpeed = 0) then
  377.            begin
  378.               FPeak := 0;                          { reset the peak }
  379.               FPeakCounter := 0;
  380.            end
  381.            else
  382.            begin
  383.               dec(FPeak);                          { dec the peak spot }
  384.               FPeakCounter := FPeakSpeed;
  385.            end;
  386.            FRefresh := True;
  387.         end;
  388.      end;
  389.   end;
  390. end;
  391. {-- TMMCustomLevel ------------------------------------------------------}
  392. constructor TMMCustomLevel.Create(AOwner: TComponent);
  393. begin
  394.    inherited Create(AOwner);
  395.    FBarDIB := TMMDIBCanvas.Create(Self);
  396.    FTimerID := 0;
  397.    FRange := $7FFF;                                { 32768 - 16 bit (abs) }
  398.    FEnabled := True;
  399.    FKind := lkHorizontal;
  400.    FDirection := dirNormal;
  401.    FBar1Color := clAqua;
  402.    FBar2Color := clAqua;
  403.    FBar3Color := clRed;
  404.    FInact1Color := clTeal;
  405.    FInact2Color := clTeal;
  406.    FInact3Color := clMaroon;
  407.    FInactiveDoted := False;
  408.    FActiveDoted := False;
  409.    FSpotSpace := 1;
  410.    FSpotWidth := 1;
  411.    FBits := b8Bit;
  412.    FChannel := chBoth;
  413.    FMode := mMono;
  414.    FDrawScale := False;
  415.    FNumPeaks := 1;
  416.    FPeakDelay := 20;
  417.    FPeakSpeed := 0;
  418.    FPeakCounter := 0;
  419.    FData := 0;
  420.    FDecay := 1;
  421.    FDecayMode := dmNone;
  422.    FDecayFactor := 0.0001;
  423.    FDecayCount := 1;
  424.    FDecayCntAct := 0;
  425.    FDecayPtr := 0;
  426.    FCurPeak := 0;
  427.    FPeak := 0;
  428.    FGain := 8;                                    { no Gain = 8 div 8 = 1 }
  429.    FSamples := 50;
  430.    FPoint1 := 50;
  431.    FPoint2 := 85;
  432.    FRefresh := False;
  433.    FSensitivy := -35;
  434.    FLogAmp := True;
  435.    FDCOffsetL := 0;
  436.    FDCOffsetR := 0;
  437.    FDrawReversed := False;
  438.    SetBounds(0,0,200,17);
  439.    Color := clBlack;
  440.    ParentFont := False;
  441.    Font.Name := 'Small Fonts';
  442.    Font.Size := 7;
  443.    SetBytesPerLevel;
  444.    if not (csDesigning in ComponentState) then
  445.    begin
  446.       { create the peak timer }
  447.       FTimerID := MMTimeSetEvent(25, False, TimeCallBack, Longint(Self));
  448.    end;
  449.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  450.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  451. end;
  452. {-- TMMCustomLevel ------------------------------------------------------}
  453. Destructor TMMCustomLevel.Destroy;
  454. begin
  455.    if (FTimerID <> 0) then
  456.    begin
  457.       { destroy the peak timer }
  458.       MMTimeKillEvent(FTimerID);
  459.    end;
  460.    FBarDIB.Free;
  461.    inherited Destroy;
  462. end;
  463. {-- TMMCustomLevel ------------------------------------------------------}
  464. procedure TMMCustomLevel.ChangeDesigning(aValue: Boolean);
  465. begin
  466.    inherited ChangeDesigning(aValue);
  467.    if not (csDesigning in ComponentState) then
  468.    begin
  469.       { create the peak timer }
  470.       if (FTimerID = 0) then
  471.           FTimerID := MMTimeSetEvent(25, False, TimeCallBack, Longint(Self));
  472.    end;
  473. end;
  474. {-- TMMCustomLevel ------------------------------------------------------}
  475. procedure TMMCustomLevel.SetBPP(aValue: integer);
  476. begin
  477.    if (aValue <> BitsPerPixel) then
  478.    begin
  479.       if (aValue <> 8) and (aValue <> 24) then
  480.          raise EMMDIBError.Create('Bitlength not supported yet');
  481.       FBarDIB.BitsPerPixel := aValue;
  482.       DIBCanvas.BitsPerPixel := aValue;
  483.       DrawInactiveSpots;
  484.       Invalidate;
  485.    end;
  486. end;
  487. {-- TMMCustomLevel ------------------------------------------------------}
  488. procedure TMMCustomLevel.GainOverflow;
  489. begin
  490.    if Assigned(FOnGainOverflow) then FOnGainOverflow(Self);
  491. end;
  492. {-- TMMCustomLevel ------------------------------------------------------}
  493. procedure TMMCustomLevel.PcmOverflow;
  494. begin
  495.    if Assigned(FOnPcmOverflow) then FOnPcmOverflow(Self);
  496. end;
  497. {-- TMMCustomLevel ------------------------------------------------------}
  498. procedure TMMCustomLevel.ResetDecayBuffers;
  499. var
  500.    i: integer;
  501. begin
  502.    FDecayPtr := 0;
  503.    FDecayCntAct := 0;      { Restart the count of number of samples taken }
  504.    FLastVal := 0;
  505.    FLastVal_F := 0;
  506.    for i := 0 to MAXDECAYCOUNT-1 do FDataBuf[i] := 0;
  507. end;
  508. {-- TMMCustomLevel ------------------------------------------------------}
  509. procedure TMMCustomLevel.ResetData;
  510. begin
  511.    FPeak := 0;
  512.    FPeakCounter := 0;
  513.    FData := 0;
  514.    FCurPeak := 0;
  515.    ResetDecayBuffers;
  516.    Refresh;
  517. end;
  518. {-- TMMCustomLevel ------------------------------------------------------}
  519. procedure TMMCustomLevel.SetDecayMode(aValue: TMMDecayMode);
  520. begin
  521.    { Select averaging mode }
  522.    if (aValue <> FDecayMode) then
  523.    begin
  524.       FDecayMode := aValue;
  525.       { Re-initialize the buffers }
  526.       ResetDecayBuffers;
  527.    end;
  528. end;
  529. {-- TMMCustomLevel ------------------------------------------------------}
  530. procedure TMMCustomLevel.SetDecay(aValue: integer);
  531. var
  532.    i: integer;
  533. begin
  534.    aValue := MinMax(aValue,1,16);
  535.    if (aValue <> FDecay) then
  536.    begin
  537.       FDecay := aValue;
  538.       { factor for stepUp and exponential averaging }
  539.       FDecayFactor := 0.0001;
  540.       for i := 0 to FDecay-1 do
  541.           FDecayFactor := sqrt(FDecayFactor);
  542.       { counter for uniform averaging }
  543.       FDecayCount := MinMax(2*(aValue-1),1,MaxDecayCount);
  544.       { Re-initialize the buffers for uniform averaging }
  545.       if (FDecayMode = dmUniform) then ResetDecayBuffers;
  546.    end;
  547.    {$IFDEF WIN32}
  548.    {$IFDEF TRIAL}
  549.    {$DEFINE _HACK1}
  550.    {$I MMHACK.INC}
  551.    {$ENDIF}
  552.    {$ENDIF}
  553. end;
  554. {-- TMMCustomLevel ------------------------------------------------------}
  555. procedure TMMCustomLevel.SetPeakDelay(aValue: integer);
  556. begin
  557.    aValue := MinMax(aValue, 0, 50);
  558.    if (aValue <> FPeakDelay) then
  559.    begin
  560.       FPeakDelay := aValue;
  561.       FPeakCounter := 0;
  562.       Invalidate;
  563.    end;
  564.    {$IFDEF WIN32}
  565.    {$IFDEF TRIAL}
  566.    {$DEFINE _HACK2}
  567.    {$I MMHACK.INC}
  568.    {$ENDIF}
  569.    {$ENDIF}
  570. end;
  571. {-- TMMCustomLevel ------------------------------------------------------}
  572. procedure TMMCustomLevel.SetPeakSpeed(aValue: integer);
  573. begin
  574.    aValue := MinMax(aValue, 0, 50);
  575.    if (aValue <> FPeakSpeed) then
  576.    begin
  577.       FPeakSpeed := aValue;
  578.       FPeakCounter := 0;
  579.       Invalidate;
  580.    end;
  581. end;
  582. {-- TMMCustomLevel ------------------------------------------------------}
  583. procedure TMMCustomLevel.SetNumPeaks(aValue: integer);
  584. begin
  585.    aValue := MinMax(aValue, 0, 5);
  586.    if (aValue <> FNumPeaks) then
  587.    begin
  588.       FNumPeaks := aValue;
  589.       FPeakCounter := 0;
  590.       if (FNumPeaks = 0) then
  591.          MMTimeSuspendEvent(FTimerID)
  592.       else if FEnabled then
  593.          MMTimeResumeEvent(FTimerID);
  594.       Invalidate;
  595.    end;
  596. end;
  597. {-- TMMCustomLevel ------------------------------------------------------}
  598. procedure TMMCustomLevel.SetEnabled(aValue: Boolean);
  599. begin
  600.    if (aValue <> FEnabled) then
  601.    begin
  602.       FEnabled := aValue;
  603.       { inherited Enabled := Value }
  604.       if (not FEnabled) then
  605.       begin
  606.          ResetData;
  607.          MMTimeSuspendEvent(FTimerID);
  608.       end
  609.       else
  610.       begin
  611.          CalcNumSpots;                     { init FData when in designing }
  612.          MMTimeResumeEvent(FTimerID);
  613.       end;
  614.       Invalidate;
  615.    end;
  616. end;
  617. {-- TMMCustomLevel ------------------------------------------------------}
  618. procedure TMMCustomLevel.SetKind(aValue: TMMLevelKind);
  619. var
  620.    Temp: integer;
  621. begin
  622.    if (aValue <> FKind) then
  623.    begin
  624.       FKind := aValue;
  625.       if ((FKind = lkHorizontal) and (Height > Width)) or
  626.          ((FKind = lkVertical) and (Height < Width)) then
  627.       begin
  628.          Temp := Width;
  629.          Width := Height;                        { swap Width and Height }
  630.          Height := Temp;
  631.       end;
  632.       Changed;                                    { recalc the dimension }
  633.       Invalidate;
  634.    end;
  635. end;
  636. {-- TMMCustomLevel ------------------------------------------------------}
  637. procedure TMMCustomLevel.SetDirection(aValue: TMMLevelDirection);
  638. Begin
  639.    if (aValue <> FDirection) then
  640.    begin
  641.       FDirection := aValue;
  642.       DrawInactiveSpots;
  643.       Invalidate;
  644.    end;
  645. end;
  646. {-- TMMCustomLevel ------------------------------------------------------}
  647. procedure TMMCustomLevel.SetSpotSpace(aValue: integer);
  648. begin
  649.    aValue := MinMax(aValue, 0, 10);
  650.    if (aValue <> FSpotSpace) then
  651.    begin
  652.       FSpotSpace := aValue;
  653.       CalcNumSpots;
  654.       Invalidate;
  655.    end;
  656.    {$IFDEF WIN32}
  657.    {$IFDEF TRIAL}
  658.    {$DEFINE _HACK3}
  659.    {$I MMHACK.INC}
  660.    {$ENDIF}
  661.    {$ENDIF}
  662. end;
  663. {-- TMMCustomLevel ------------------------------------------------------}
  664. procedure TMMCustomLevel.SetSpotWidth(aValue: integer);
  665. Var
  666.    Temp: integer;
  667. begin
  668.    Temp := 0;
  669.    case FKind of
  670.       lkHorizontal: Temp := FWidth div 3;
  671.       lkVertical  : Temp := FHeight div 3;
  672.    end;
  673.    aValue := MinMax(aValue, 1, Temp);
  674.    if (aValue <> FSpotWidth) then
  675.    begin
  676.       FSpotWidth := aValue;
  677.       CalcNumSpots;
  678.       Invalidate;
  679.    end;
  680. end;
  681. {-- TMMCustomLevel ------------------------------------------------------}
  682. procedure TMMCustomLevel.SetSensitivy(aValue: integer);
  683. begin
  684.    aValue := MinMax(aValue, -90, -9);
  685.    if (aValue <> FSensitivy) then
  686.    begin
  687.       FSensitivy := aValue;
  688.    end;
  689. end;
  690. {-- TMMCustomLevel ------------------------------------------------------}
  691. procedure TMMCustomLevel.SetLogAmp(aValue: Boolean);
  692. begin
  693.    if (aValue <> FLogAmp) then
  694.    begin
  695.       FLogAmp := aValue;
  696.       Invalidate;
  697.    end;
  698. end;
  699. {-- TMMCustomLevel ------------------------------------------------------}
  700. procedure TMMCustomLevel.CalcNumSpots;
  701. begin
  702.    FSpotWidth := Max(FSpotWidth,1);
  703.    if (FKind = lkHorizontal) then
  704.    begin
  705.       FNumSpots := (FWidth+FSpotSpace) div (FSpotWidth+FSpotSpace);
  706.       FNumSpots := Max(FNumSpots,1);          { fix div by zerro !!! }
  707.       FFirstSpace := (FWidth-(FNumSpots*(FSpotWidth+FSpotSpace)-FSpotSpace)) div 2;
  708.    end
  709.    else
  710.    begin
  711.       FNumSpots := (FHeight+FSpotSpace)div(FSpotWidth+FSpotSpace);
  712.       FNumSpots := Max(FNumSpots,1);           { fix div by zerro !!! }
  713.       FFirstSpace := (FHeight-(FNumSpots*(FSpotWidth+FSpotSpace)-FSpotSpace)) div 2;
  714.    end;
  715.    { calc the spot on which the next color starts }
  716.    FPoint1Spot := (FPoint1 * FNumSpots) div 100;
  717.    FPoint2Spot := (FPoint2 * FNumSpots) div 100;
  718.    { redraw background }
  719.    DrawInactiveSpots;
  720.    { we will see anything in designer }
  721.    if (csDesigning in ComponentState) and FEnabled then
  722.    begin
  723.       if (FPoint2Spot < FNumSpots) then
  724.          FData := FPoint2Spot + ((FNumSpots-FPoint2Spot) div 2)
  725.       else if (FPoint1Spot < FNumSpots) then
  726.          FData := FPoint1Spot + ((FNumSpots-FPoint1Spot) div 2)
  727.       else
  728.          FData := FNumSpots - (FNumSpots div 4);
  729.    end
  730.    else
  731.    begin
  732.       FPeak := 0;
  733.       FData := 0;
  734.    end;
  735. end;
  736. {-- TMMCustomLevel ------------------------------------------------------}
  737. procedure TMMCustomLevel.SetBounds(aLeft, aTop, aWidth, aHeight: integer);
  738. begin
  739.    inherited SetBounds(aLeft, aTop, aWidth, aHeight);
  740.    Changed;
  741. end;
  742. {-- TMMCustomLevel ------------------------------------------------------}
  743. procedure TMMCustomLevel.Loaded;
  744. begin
  745.    inherited Loaded;
  746.    DrawInactiveSpots;
  747.    Invalidate;
  748. end;
  749. {-- TMMCustomLevel ------------------------------------------------------}
  750. procedure TMMCustomLevel.Changed;
  751. begin
  752.    FClientRect := BeveledRect;
  753.    FWidth  := Max(FClientRect.Right - FClientRect.Left,1);
  754.    FHeight := Max(FClientRect.Bottom - FClientRect.Top,1);
  755.    DIBCanvas.SetBounds(0,0,FWidth,FHeight);
  756.    FBarDIB.SetBounds(0,0,FWidth,FHeight);
  757.    { recalculate the number of spots }
  758.    CalcNumSpots;
  759.    inherited Changed;
  760. end;
  761. {-- TMMCustomLevel ------------------------------------------------------}
  762. procedure TMMCustomLevel.SetBytesPerLevel;
  763. begin
  764.    FBytes := (Ord(FBits)+1) * (Ord(FMode)+1) * FSamples;
  765. end;
  766. {-- TMMCustomLevel ------------------------------------------------------}
  767. procedure TMMCustomLevel.SetSamples(aValue: integer);
  768. begin
  769.    aValue := Max(aValue, 1);
  770.    if (aValue <> FSamples) then
  771.    begin
  772.       FSamples := aValue;
  773.       SetBytesPerLevel;
  774.    end;
  775. end;
  776. {-- TMMCustomLevel ------------------------------------------------------}
  777. procedure TMMCustomLevel.SetPCMWaveFormat(wf: TPCMWaveFormat);
  778. var
  779.    pwfx: PWaveFormatEx;
  780. begin
  781.    pwfx := @wf;
  782.    if not pcmIsValidFormat(pwfx) then
  783.       raise EMMLevelError.Create(LoadResStr(IDS_INVALIDFORMAT));
  784.    BitLength := TMMBits(pwfx^.wBitsPerSample div 8 - 1);
  785.    Mode := TMMMode(pwfx^.nChannels-1);
  786. end;
  787. {-- TMMCustomLevel ------------------------------------------------------}
  788. function TMMCustomLevel.GetPCMWaveFormat: TPCMWaveFormat;
  789. var
  790.    wfx: TWaveFormatEx;
  791. begin
  792.    pcmBuildWaveHeader(@wfx, (Ord(FBits)+1)*8, Ord(FMode)+1, 11025);
  793.    Result := PPCMWaveFormat(@wfx)^;
  794. end;
  795. {-- TMMCustomLevel ------------------------------------------------------}
  796. procedure TMMCustomLevel.SetBits(aValue: TMMBits);
  797. begin
  798.    if (aValue <> FBits) then
  799.    begin
  800.       FBits := aValue;
  801.       SetBytesPerLevel;
  802.       Invalidate;
  803.    end;
  804. end;
  805. {-- TMMCustomLevel ------------------------------------------------------}
  806. procedure TMMCustomLevel.SetChannel(aValue: TMMChannel);
  807. begin
  808.    if (aValue <> FChannel) then
  809.    begin
  810.       FChannel := aValue;
  811.       SetBytesPerLevel;
  812.       Invalidate;
  813.    end;
  814.    {$IFDEF WIN32}
  815.    {$IFDEF TRIAL}
  816.    {$DEFINE _HACK2}
  817.    {$I MMHACK.INC}
  818.    {$ENDIF}
  819.    {$ENDIF}
  820. end;
  821. {-- TMMCustomLevel ------------------------------------------------------}
  822. procedure TMMCustomLevel.SetMode(aValue: TMMMode);
  823. begin
  824.    if (aValue <> FMode) then
  825.    begin
  826.       FMode := aValue;
  827.       SetBytesPerLevel;
  828.       Invalidate;
  829.    end;
  830. end;
  831. {-- TMMCustomLevel ------------------------------------------------------}
  832. procedure TMMCustomLevel.SetGain(aValue: Integer);
  833. begin
  834.    if (aValue <> FGain-8) AND (aValue >= -8) AND (aValue <= 32) then
  835.    begin
  836.       FGain := aValue + 8;
  837.       Invalidate;
  838.    end;
  839. end;
  840. {-- TMMCustomLevel ------------------------------------------------------}
  841. function TMMCustomLevel.GetGain: Integer;
  842. begin
  843.    Result := FGain - 8;
  844. end;
  845. {-- TMMCustomLevel ------------------------------------------------------}
  846. procedure TMMCustomLevel.SetPoints(Index, aValue: integer);
  847. begin
  848.    aValue := MinMax(aValue, 1, 100);
  849.    case Index of
  850.      0: if FPoint1 = aValue then exit else FPoint1 := aValue;
  851.      1: if FPoint2 = aValue then exit else FPoint2 := aValue;
  852.    end;
  853.    CalcNumSpots;
  854.    Invalidate;
  855. end;
  856. {-- TMMCustomLevel ------------------------------------------------------}
  857. procedure TMMCustomLevel.SetColors(Index:Integer; aValue: TColor);
  858. begin
  859.    case Index of
  860.       0: if FBar1Color = aValue then exit else FBar1Color := aValue;
  861.       1: if FBar2Color = aValue then exit else FBar2Color := aValue;
  862.       2: if FBar3Color = aValue then exit else FBar3Color := aValue;
  863.       3: if FInact1Color = aValue then exit else FInact1Color := aValue;
  864.       4: if FInact2Color = aValue then exit else FInact2Color := aValue;
  865.       5: if FInact3Color = aValue then exit else FInact3Color := aValue;
  866.    end;
  867.    DrawInactiveSpots;
  868.    Invalidate;
  869. end;
  870. {-- TMMCustomLevel ------------------------------------------------------}
  871. procedure TMMCustomLevel.SetDCOffset(Index,aValue: Integer);
  872. begin
  873.    case Index of
  874.       0: if FDCOffsetL = aValue then exit else FDCOffsetL := -aValue;
  875.       1: if FDCOffsetR = aValue then exit else FDCOffsetR := -aValue;
  876.    end;
  877. end;
  878. {-- TMMCustomLevel ------------------------------------------------------}
  879. function TMMCustomLevel.GetDCOffset(Index: Integer): integer;
  880. begin
  881.    case Index of
  882.       0: Result := -FDCOffsetL;
  883.       1: Result := -FDCOffsetR;
  884.       else Result := 0;
  885.    end;
  886. end;
  887. {-- TMMCustomLevel ------------------------------------------------------}
  888. procedure TMMCustomLevel.SetInactiveDoted(aValue: Boolean);
  889. begin
  890.    if (aValue <> FInactiveDoted) then
  891.    begin
  892.       FInactiveDoted := aValue;
  893.       DrawInactiveSpots;
  894.       Invalidate;
  895.    end;
  896. end;
  897. {-- TMMCustomLevel ------------------------------------------------------}
  898. procedure TMMCustomLevel.SetActiveDoted(aValue: Boolean);
  899. begin
  900.    if (aValue <> FActiveDoted) then
  901.    begin
  902.       FActiveDoted := aValue;
  903.       DrawInactiveSpots;
  904.       Invalidate;
  905.    end;
  906. end;
  907. {-- TMMCustomLevel ------------------------------------------------------}
  908. procedure TMMCustomLevel.CMColorChanged(var Message: TMessage);
  909. begin
  910.    DrawInactiveSpots;
  911.    inherited;
  912. end;
  913. {-- TMMCustomLevel ------------------------------------------------------}
  914. Procedure TMMCustomLevel.RefreshPCMData(PCMData: Pointer);
  915. Var
  916.    i: integer;
  917.    ReIndex: integer;
  918.    BestValue,Value,DCOffs: integer;
  919. begin
  920.    if FEnabled and Visible then
  921.    begin
  922.       BestValue := 0;
  923.       ReIndex := Ord(FChannel)-1;
  924.       if (FBits = b8bit) then
  925.          if (FMode = mMono) then
  926.          for i := 0 to FSamples-1 do
  927.          begin
  928.             Value := ABS((PByteArray(PCMData)^[i]+FDCOffsetL-128) shl 8);
  929.             if (Value > BestValue) then BestValue := Value;
  930.          end
  931.          else if (FChannel = chBoth) then
  932.          for i := 0 to FSamples-1 do
  933.          begin
  934.             Value := ABS(((Word(PByteArray(PCMData)^[i+i]+FDCOffsetL)+PByteArray(PCMData)^[i+i+1]+FDCOffsetR)div 2-128) shl 8);
  935.             if (Value > BestValue) then BestValue := Value;
  936.          end
  937.          else
  938.          begin
  939.             if (FChannel = chLeft) then
  940.                 DCOffs := FDCOffsetL
  941.             else
  942.                 DCOffs := FDCOffsetR;
  943.             for i := 0 to FSamples-1 do
  944.             begin
  945.                Value := ABS((PByteArray(PCMData)^[i+i+ReIndex]+DCOffs-128) shl 8);
  946.                if (Value > BestValue) then BestValue := Value;
  947.             end;
  948.          end
  949.       else
  950.          if (FMode = mMono) then
  951.          for i := 0 to FSamples-1 do
  952.          begin
  953.             Value := ABS(PSmallArray(PCMData)^[i]+FDCOffsetL);
  954.             if (Value > BestValue) then BestValue := Value;
  955.          end
  956.          else if (FChannel = chBoth) then
  957.          for i := 0 to FSamples-1 do
  958.          begin
  959.             Value := ABS((Long(PSmallArray(PCMData)^[i+i]+FDCOffsetL)+PSmallArray(PCMData)^[i+i+1]+FDCOffsetR)div 2);
  960.             if (Value > BestValue) then BestValue := Value;
  961.          end
  962.          else
  963.          begin
  964.             if (FChannel = chLeft) then
  965.                 DCOffs := FDCOffsetL
  966.             else
  967.                 DCOffs := FDCOffsetR;
  968.             for i := 0 to FSamples-1 do
  969.             begin
  970.                Value := ABS(PSmallArray(PCMData)^[i+i+ReIndex]+DCOffs);
  971.                if (Value > BestValue) then BestValue := Value;
  972.             end;
  973.          end;
  974.       if (BestValue >= FRange) then PcmOverflow;
  975.       SetData(BestValue);
  976.    end;
  977. end;
  978. {-- TMMCustomLevel ------------------------------------------------------}
  979. procedure TMMCustomLevel.SetData(SampleValue: integer);
  980. var
  981.    dbValue: Float;
  982. begin
  983.    SampleValue := abs(SampleValue);
  984.    FCurPeak := SampleValue;
  985.    if (SampleValue = 0) and (FData = 0) and not FRefresh then exit;
  986.    if (FDecayMode <> dmNone) then
  987.    begin
  988.       inc(FDecayPtr);
  989.       inc(FDecayCntAct);
  990.       if (FDecayPtr >= FDecayCount) then FDecayPtr := 0;
  991.       if (FDecayCntAct > FDecayCount) then FDecayCntAct := FDecayCount;
  992.       { In decay mode, need to average the value }
  993.       case Ord(FDecayMode) of
  994.         1: begin
  995.               FLastVal_F := FLastVal_F*FDecayFactor;
  996.               if (SampleValue > FLastVal_F) then FLastVal_F := SampleValue
  997.               else SampleValue := Trunc(FLastVal_F);
  998.            end;
  999.         2: begin
  1000.       FLastVal_F := FLastVal_F*FDecayFactor+(1-FDecayFactor)*SampleValue;
  1001.       SampleValue := Floor(FLastVal_F);
  1002.            end;
  1003.         3: begin
  1004.               FLastVal := FLastVal+(SampleValue-FDataBuf[FDecayPtr]);
  1005.               FDataBuf[FDecayPtr] := SampleValue;
  1006.               SampleValue := FLastVal div FDecayCntAct;
  1007.            end;
  1008.       end;
  1009.    end;
  1010.    if FLogAmp then
  1011.    begin
  1012.       { add the gain and calc the actual db value }
  1013.       dbValue := Log10(MaxR(MulDiv32(SampleValue,FGain,8)/FRange,0.000001))*20;
  1014.       { now the scaling }
  1015.       SampleValue := Max(Round((dbValue-FSensitivy)*FNumSpots/-FSensitivy),0);
  1016.    end
  1017.    else
  1018.    begin
  1019.       { calc the low limit (Sensivity(db) to sample value }
  1020.       dbValue := FRange/pow(10,-FSensitivy/20);
  1021.       { now the scaling }
  1022.       SampleValue := Max(Round((MulDiv32(SampleValue,FGain,8)-dbValue)*FNumSpots/(FRange-dbValue)),0);
  1023.    end;
  1024.    if (Direction = dirSymetric) then
  1025.        SampleValue := SampleValue div 2;
  1026.    if FDrawReversed then
  1027.       SampleValue := FNumSpots-SampleValue;
  1028.    if (SampleValue > FNumSpots) then
  1029.    begin
  1030.       GainOverflow;
  1031.       SampleValue := FNumSpots;
  1032.    end;
  1033.    if (SampleValue >= FPeak) and (SampleValue > 0) and (FNumPeaks > 0) then
  1034.    begin
  1035.       FRefresh := True;
  1036.       FPeak := SampleValue;                          {start a new peak timer }
  1037.       FPeakCounter := (FPeakDelay*2)+1;
  1038.    end;
  1039.    if (SampleValue <> FData) or FRefresh then
  1040.    begin
  1041.       FRefresh := False;
  1042.       FData := SampleValue;
  1043.       if FEnabled and Visible then
  1044.          FastDraw(DrawLevel,False);
  1045.    end;
  1046. end;
  1047. {-- TMMCustomLevel ------------------------------------------------------}
  1048. procedure TMMCustomLevel.SetValue(aValue: integer);
  1049. begin
  1050.    SetData(Round(MinMax(aValue,0,VALUERANGE)*FRange/VALUERANGE));
  1051. end;
  1052. {-- TMMCustomLevel ------------------------------------------------------}
  1053. function TMMCustomLevel.GetValue: integer;
  1054. begin
  1055.    if FData = 0 then
  1056.       Result := 0
  1057.    else if not FLogAmp then
  1058.       Result := Round(FData * VALUERANGE / FNumSpots)
  1059.    else
  1060.       Result := Round(pow(10,(FSensitivy-FSensitivy*FData/FNumspots)/20)
  1061.                           * 8 / FGain * VALUERANGE);
  1062. end;
  1063. {-- TMMCustomLevel ------------------------------------------------------}
  1064. function TMMCustomLevel.GetPeak: integer;
  1065. begin
  1066.    if FPeak = 0 then
  1067.       Result := 0
  1068.    else if not FLogAmp then
  1069.       Result := Round(FPeak * VALUERANGE / FNumSpots)
  1070.    else
  1071.       Result := Round(pow(10,(FSensitivy-FSensitivy*FPeak/FNumspots)/20)
  1072.                           * 8 / FGain * VALUERANGE);
  1073. end;
  1074. {-- TMMCustomLevel ------------------------------------------------------}
  1075. function TMMCustomLevel.GetPeakValue: integer;
  1076. begin
  1077.   Result := (GetPeak * FRange) div VALUERANGE;
  1078. end;
  1079. {-- TMMCustomLevel ------------------------------------------------------}
  1080. procedure TMMCustomLevel.SetOnDrawBar(aValue: TMMLevelDrawBar);
  1081. begin
  1082.    FOnDrawBar := aValue;
  1083.    if not assigned(FOnDrawBar) then DrawInactiveSpots;
  1084.    Invalidate;
  1085. end;
  1086. {-- TMMCustomLevel ------------------------------------------------------}
  1087. procedure TMMCustomLevel.DrawLevelHorizontal(DIB: TMMDIBCanvas; nSpots, Peak: integer; DrawAll: Boolean);
  1088. Var
  1089.    i: integer;
  1090.    SpotRect: TRect;                                 { Spot draw rectangle }
  1091.    SpotInc: integer;                       { increase value for next spot }
  1092. begin
  1093.    SpotInc := FSpotWidth + FSpotSpace;
  1094.    SpotRect.Top := 0;
  1095.    SpotRect.Bottom := FHeight;
  1096.    if (FDirection = dirNormal) then
  1097.    begin
  1098.       SpotRect.Left := FFirstSpace;
  1099.       SpotRect.Right := SpotRect.Left + FSpotWidth;             {Leerraum }
  1100.    end
  1101.    else
  1102.    begin
  1103.       SpotRect.Right := FWidth - FFirstSpace;
  1104.       SpotRect.Left := SpotRect.Right - FSpotWidth;
  1105.       SpotInc := -SpotInc;
  1106.    end;
  1107.    with DIB do
  1108.    begin
  1109.       if not DrawAll and (Direction = dirSymetric) then
  1110.       begin
  1111.          if (nSpots > FNumSpots) then nSpots := FNumSpots
  1112.          else if (nSpots < 1) then nSpots := 1;
  1113.          OffsetRect(SpotRect, (nSpots-1-SYNCBARS)*SpotInc, 0);
  1114.          for i := 0 to 2*SYNCBARS do   { draw the highlited spots }
  1115.          begin
  1116.             if (nSpots > FPoint2Spot) then DIB_SetTColor(FBar3Color)
  1117.             else if (nSpots > FPoint1Spot) then DIB_SetTColor(FBar2Color)
  1118.             else DIB_SetTColor(FBar1Color);
  1119.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1120.             OffsetRect(SpotRect, SpotInc, 0);
  1121.          end;
  1122.       end
  1123.       else
  1124.       begin
  1125.          DIB_SetTColor(FBar1Color);
  1126.          for i := 1 to nSpots do { draw the highlited spots }
  1127.          begin
  1128.             if i > FPoint2Spot then DIB_SetTColor(FBar3Color)
  1129.             else if i > FPoint1Spot then DIB_SetTColor(FBar2Color);
  1130.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1131.             OffsetRect(SpotRect, SpotInc, 0);
  1132.          end;
  1133.       end;
  1134.       if (FNumPeaks > 0) and (Peak > nSpots) then
  1135.       begin
  1136.          OffsetRect(SpotRect, ((Peak-1)-nSpots)*SpotInc, 0);
  1137.          for i := 0 to FNumPeaks-1 do       { draw the peak spots }
  1138.          begin
  1139.             if Peak-i  > FPoint2Spot then DIB_SetTColor(FBar3Color)
  1140.             else if Peak-i > FPoint1Spot then DIB_SetTColor(FBar2Color)
  1141.             else DIB_SetTColor(FBar1Color);
  1142.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1143.             OffsetRect(SpotRect, -SpotInc, 0);
  1144.          end;
  1145.       end;
  1146.    end;
  1147. end;
  1148. {-- TMMCustomLevel ------------------------------------------------------}
  1149. procedure TMMCustomLevel.DrawLevelVertical(DIB: TMMDIBCanvas; nSpots, Peak: integer; DrawAll: Boolean);
  1150. Var
  1151.    i: integer;
  1152.    SpotRect: TRect;                                 { Spot draw rectangle }
  1153.    SpotInc: integer;                       { increase value for next spot }
  1154. begin
  1155.    SpotInc := FSpotWidth + FSpotSpace;
  1156.    SpotRect.Left := 0;
  1157.    SpotRect.Right := FWidth;
  1158.    with DIB do
  1159.    begin
  1160.       if (FDirection = dirNormal) then
  1161.       begin
  1162.          SpotRect.Bottom := FHeight - FFirstSpace;
  1163.          SpotRect.Top := SpotRect.Bottom - FSpotWidth;
  1164.          SpotInc := -SpotInc;
  1165.       end
  1166.       else
  1167.       begin
  1168.          SpotRect.Top := FFirstSpace;
  1169.          SpotRect.Bottom := SpotRect.Top + FSpotWidth;
  1170.       end;
  1171.       if not DrawAll and (Direction = dirSymetric) then
  1172.       begin
  1173.          if (nSpots > FNumSpots) then nSpots := FNumSpots
  1174.          else if (nSpots < 1) then nSpots := 1;
  1175.          OffsetRect(SpotRect, 0, (nSpots-1-SYNCBARS)*SpotInc);
  1176.          for i := 0 to 2*SYNCBARS do   { draw the highlited spots }
  1177.          begin
  1178.             if (nSpots > FPoint2Spot) then DIB_SetTColor(FBar3Color)
  1179.             else if (nSpots > FPoint1Spot) then DIB_SetTColor(FBar2Color)
  1180.             else DIB_SetTColor(FBar1Color);
  1181.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1182.             OffsetRect(SpotRect, 0, SpotInc);
  1183.          end;
  1184.       end
  1185.       else
  1186.       begin
  1187.          DIB_SetTColor(FBar1Color);
  1188.          for i := 1 to nSpots do                 { draw the highlited spots }
  1189.          begin
  1190.             if i > FPoint2Spot then DIB_SetTColor(FBar3Color)
  1191.             else if i > FPoint1Spot then DIB_SetTColor(FBar2Color);
  1192.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1193.             OffsetRect(SpotRect, 0, SpotInc);
  1194.          end;
  1195.       end;
  1196.       if (FNumPeaks > 0) and (Peak > nSpots) then
  1197.       begin
  1198.          OffsetRect(SpotRect, 0, ((Peak-1)-nSpots) * SpotInc);
  1199.          for i := 0 to FNumPeaks-1 do       { draw the peak spots }
  1200.          begin
  1201.             if Peak-i  > FPoint2Spot then DIB_SetTColor(FBar3Color)
  1202.             else if Peak-i > FPoint1Spot then DIB_SetTColor(FBar2Color)
  1203.             else DIB_SetTColor(FBar1Color);
  1204.             DIB_FillRectDoted(SpotRect,FActiveDoted);
  1205.             OffsetRect(SpotRect, 0, -SpotInc);
  1206.          end;
  1207.       end;
  1208.    end;
  1209. end;
  1210. {-- TMMCustomLevel ------------------------------------------------------}
  1211. procedure TMMCustomLevel.DrawInactiveSpots;
  1212. var
  1213.    _Bar1,_Bar2,_Bar3: TColor;
  1214.    _Active: Boolean;
  1215. begin
  1216.    if not (csLoading in ComponentState) and (FBarDIB <> nil) and not assigned(FOnDrawBar) then
  1217.    with FBarDIB do
  1218.    begin
  1219.       DIB_InitDrawing;
  1220.       DIB_SetTColor(Color);
  1221.       DIB_Clear;
  1222.       _Bar1 := FBar1Color;
  1223.       _Bar2 := FBar2Color;
  1224.       _Bar3 := FBar3Color;
  1225.       _Active := FActiveDoted;
  1226.       FBar1Color := FInact1Color;
  1227.       FBar2Color := FInact2Color;
  1228.       FBar3Color := FInact3Color;
  1229.       FActiveDoted := FInactiveDoted;
  1230.       case FKind of
  1231.          lkHorizontal: DrawLevelHorizontal(FBarDIB,FNumSpots,0,True);
  1232.          lkVertical  : DrawLevelVertical(FBarDIB,FNumSpots,0,True);
  1233.       end;
  1234.       FBar1Color := _Bar1;
  1235.       FBar2Color := _Bar2;
  1236.       FBar3Color := _Bar3;
  1237.       FActiveDoted := _Active;
  1238.       DIB_DoneDrawing;
  1239.    end;
  1240. end;
  1241. {-- TMMCustomLevel ------------------------------------------------------}
  1242. procedure TMMCustomLevel.DrawLevel(Dummy: Boolean);
  1243. begin
  1244.    if assigned(FOnPaint) then FOnPaint(Self);
  1245.    DIBCanvas.DIB_InitDrawing;
  1246.                                                    { draw the background }
  1247.    if assigned(FOnDrawBar) then
  1248.    begin
  1249.       FOnDrawBar(Self,DIBCanvas,Rect(0,0,FWidth,FHeight),FData,FPeak);
  1250.    end
  1251.    else
  1252.    begin
  1253.       DIBCanvas.DIB_CopyDIBBits(FBarDIB.Surface,0,0,FWidth,FHeight,0,0);
  1254.       if FEnabled then
  1255.       begin
  1256.          case FKind of                           { draw the level to bitmap }
  1257.            lkHorizontal: DrawLevelHorizontal(DIBCanvas,FData,FPeak,False);
  1258.            lkVertical  : DrawLevelVertical(DIBCanvas,FData,FPeak,False);
  1259.          end;
  1260.       end;
  1261.    end;
  1262.    DIBCanvas.DIB_BitBlt(Canvas.Handle,FClientRect,0,0); { copy to screen }
  1263.    DIBCanvas.DIB_DoneDrawing;
  1264. end;
  1265. {-- TMMCustomLevel ------------------------------------------------------}
  1266. Procedure TMMCustomLevel.Paint;
  1267. begin
  1268.    { draw the bevel }
  1269.    inherited Paint;
  1270.    DrawLevel(True);
  1271.    {$IFDEF BUILD_ACTIVEX}
  1272.    if Selected then
  1273.    begin
  1274.       Canvas.Brush.Style := bsClear;
  1275.       Canvas.Pen.Color   := clRed;
  1276.       Canvas.Rectangle(0,0,Width,Height);
  1277.       Canvas.Brush.Style := bsSolid;
  1278.    end;
  1279.    {$ENDIF}
  1280. end;
  1281. {== TMMLevelScale =======================================================}
  1282. constructor TMMLevelScale.Create(aOwner: TComponent);
  1283. begin
  1284.    inherited create(aOwner);
  1285.    FSensitivy := -35;
  1286.    FLogAmp := True;
  1287.    FScaleTicks := 8;
  1288.    FPoint1 := 50;
  1289.    FPoint2 := 85;
  1290.    FScale1Color := clWhite;
  1291.    FScale2Color := clWhite;
  1292.    FScale3Color := clRed;
  1293.    ParentFont := False;
  1294.    Font.Name := 'Small Fonts';
  1295.    Font.Size := 6;
  1296.    Color := clBlack;
  1297.    Width := 200;
  1298.    Height := 7;
  1299.    FScalePos := spBoth;
  1300.    FScale := TMMLevScale.Create;
  1301.    FScale.Visible := False;
  1302.    FScale.OnChange := ScaleChanged;
  1303. end;
  1304. {-- TMMLevelScale -------------------------------------------------------}
  1305. destructor TMMLevelScale.Destroy;
  1306. begin
  1307.    FScale.Free;
  1308.    inherited Destroy;
  1309. end;
  1310. {-- TMMLevelScale -------------------------------------------------------}
  1311. procedure TMMLevelScale.SetScalePos(Value: TMMScalePos);
  1312. begin
  1313.     if Value <> FScalePos then
  1314.     begin
  1315.        FScalePos := Value;
  1316.        Invalidate;
  1317.     end;
  1318. end;
  1319. {-- TMMLevelScale -------------------------------------------------------}
  1320. procedure TMMLevelScale.SetScale(Value: TMMLevScale);
  1321. begin
  1322.    FScale.Assign(Value);
  1323. end;
  1324. {-- TMMLevelScale -------------------------------------------------------}
  1325. procedure TMMLevelScale.ScaleChanged(Sender: TObject);
  1326. begin
  1327.    Invalidate;
  1328. end;
  1329. {-- TMMLevelScale -------------------------------------------------------}
  1330. procedure TMMLevelScale.SetSensitivy(aValue: integer);
  1331. begin
  1332.    aValue := MinMax(aValue, -90, -9);
  1333.    if (aValue <> FSensitivy) then
  1334.    begin
  1335.       FSensitivy := aValue;
  1336.       Invalidate;
  1337.    end;
  1338. end;
  1339. {-- TMMLevelScale -------------------------------------------------------}
  1340. procedure TMMLevelScale.SetLogAmp(aValue: Boolean);
  1341. begin
  1342.    if (aValue <> FLogAmp) then
  1343.    begin
  1344.       FLogAmp := aValue;
  1345.       Invalidate;
  1346.    end;
  1347. end;
  1348. {-- TMMLevelScale -------------------------------------------------------}
  1349. procedure TMMLevelScale.SetScaleTicks(aValue: integer);
  1350. begin
  1351.    if (aValue <> FScaleTicks) then
  1352.    begin
  1353.       FScaleTicks := Max(aValue,2);
  1354.       Invalidate;
  1355.    end;
  1356. end;
  1357. {-- TMMLevelScale -------------------------------------------------------}
  1358. procedure TMMLevelScale.SetPoints(Index, aValue: integer);
  1359. begin
  1360.    aValue := MinMax(aValue, 1, 100);
  1361.    case Index of
  1362.      0: if FPoint1 = aValue then exit else FPoint1 := aValue;
  1363.      1: if FPoint2 = aValue then exit else FPoint2 := aValue;
  1364.    end;
  1365.    Invalidate;
  1366. end;
  1367. {-- TMMLevelScale -------------------------------------------------------}
  1368. procedure TMMLevelScale.SetColors(Index:Integer; aValue: TColor);
  1369. begin
  1370.    case Index of
  1371.       0: if FScale1Color = aValue then exit else FScale1Color := aValue;
  1372.       1: if FScale2Color = aValue then exit else FScale2Color := aValue;
  1373.       2: if FScale3Color = aValue then exit else FScale3Color := aValue;
  1374.    end;
  1375.    Invalidate;
  1376. end;
  1377. {-- TMMLevelScale -------------------------------------------------------}
  1378. procedure TMMLevelScale.SetKind(aValue: TMMLevelKind);
  1379. var
  1380.    Temp: integer;
  1381. begin
  1382.    if (aValue <> FKind) then
  1383.    begin
  1384.       FKind := aValue;
  1385.       if ((FKind = lkHorizontal) and (Height > Width)) or
  1386.          ((FKind = lkVertical) and (Height < Width)) then
  1387.       begin
  1388.          Temp := Width;
  1389.          Width := Height;                        { swap Width and Height }
  1390.          Height := Temp;
  1391.       end;
  1392.       Invalidate;
  1393.    end;
  1394. end;
  1395. {-- TMMLevelScale -------------------------------------------------------}
  1396. Procedure TMMLevelScale.SetDirection(aValue: TMMLevelDirection);
  1397. Begin
  1398.    if (aValue <> FDirection) then
  1399.    begin
  1400.       FDirection := aValue;
  1401.       Invalidate;
  1402.    end;
  1403. end;
  1404. (*
  1405. {-- TMMLevelScale -------------------------------------------------------}
  1406. procedure TMMLevelScale.Paint;
  1407. const
  1408.      FRange = $7FFF;
  1409. var
  1410.    i, Count,CurValue,Volume: Longint;
  1411.    dbValue: Float;
  1412.    R        : TRect;
  1413.    Rev      : Boolean;
  1414.    P1, P2   : Integer;
  1415. begin
  1416.    with Canvas do
  1417.    begin
  1418.       Brush.Color := Color;
  1419.       FillRect(ClientRect);
  1420.       Font := Self.Font;
  1421.       R := ClientRect;
  1422.       if Scale.Visible then
  1423.       begin
  1424.         InflateRect(R,-1,-2);
  1425.         Scale.Canvas := Canvas ;
  1426.         Rev := (Kind = lkVertical) xor (Direction = dirReversed);
  1427.         if Rev then
  1428.         begin
  1429.             Scale.Color  := Scale3Color;
  1430.             Scale.Color2 := Scale2Color;
  1431.             Scale.Color3 := Scale1Color;
  1432.             P1           := 100 - Point2;
  1433.             P2           := 100 - Point1;
  1434.         end
  1435.         else
  1436.         begin
  1437.             Scale.Color  := Scale1Color;
  1438.             Scale.Color2 := Scale2Color;
  1439.             Scale.Color3 := Scale3Color;
  1440.             P1           := Point1;
  1441.             P2           := Point2;
  1442.         end;
  1443.         Scale.Point1 := MulDiv(P1-1,Scale.TickCount,100);
  1444.         Scale.Point2 := MulDiv(P2-1,Scale.TickCount,100);
  1445.         if (ScalePos = spAboveOrLeft) or (ScalePos = spBoth) then
  1446.         begin
  1447.            if Kind = lkHorizontal then
  1448.            begin
  1449.               Scale.DrawRect(Canvas,Rect(R.Left,R.Top,R.Right-1,R.Top+Scale.ScaleHeight),True);
  1450.               Inc(R.Top,Scale.ScaleHeight);
  1451.            end
  1452.            else
  1453.            begin
  1454.               Scale.DrawRect(Canvas,Rect(R.Left,R.Top,R.Left+Scale.ScaleHeight,R.Bottom-1),True);
  1455.               Inc(R.Left,Scale.ScaleHeight);
  1456.            end;
  1457.         end;
  1458.         if (ScalePos = spBelowOrRight) or (ScalePos = spBoth) then
  1459.         begin
  1460.            if Kind = lkHorizontal then
  1461.            begin
  1462.               Scale.DrawRect(Canvas,Rect(R.Left,R.Bottom-Scale.ScaleHeight,R.Right-1,R.Bottom),False);
  1463.               Dec(R.Bottom,Scale.ScaleHeight)
  1464.            end
  1465.            else
  1466.            begin
  1467.               Scale.DrawRect(Canvas,Rect(R.Right-Scale.ScaleHeight,R.Top,R.Right,R.Bottom-1),False);
  1468.               Dec(R.Right,Scale.ScaleHeight);
  1469.            end;
  1470.         end;
  1471.       end;
  1472.       if (R.Top > R.Bottom) or (R.Left > R.Right) then Exit;
  1473.       { Draw the scale }
  1474.       if FScaleTicks > 1 then
  1475.       for i := 0 to FScaleTicks-1 do
  1476.       begin
  1477.          CurValue := MulDiv(FRange,i,FScaleTicks-1);
  1478.          if ((FKind = lkHorizontal) and (FDirection = dirReversed)) or
  1479.             ((FKind = lkVertical) and (FDirection = dirNormal)) then
  1480.             CurValue := FRange - CurValue;
  1481.          if (CurValue > Long(FPoint2)*FRange/100) then Font.Color := FScale3Color
  1482.          else if (CurValue > Long(FPoint1)*FRange/100) then Font.Color := FScale2Color
  1483.          else Font.Color := FScale1Color;
  1484.          if FLogAmp then
  1485.          begin
  1486.             Count := i;
  1487.             if ((FKind = lkHorizontal) and (FDirection = dirNormal)) or
  1488.                ((FKind = lkVertical) and (FDirection = dirReversed)) then
  1489.                  Count := FScaleTicks-1-Count;
  1490.             Volume := Muldiv(Count,FSensitivy,FScaleTicks-1)
  1491.          end
  1492.          else
  1493.          begin
  1494.             Count := i;
  1495.             if ((FKind = lkHorizontal) and (FDirection = dirReversed)) or
  1496.                ((FKind = lkVertical) and (FDirection = dirNormal)) then
  1497.                  Count := FScaleTicks-1-Count;
  1498.             dbValue := FRange/pow(10,-FSensitivy/20);
  1499.             Volume := Round(Log10(((Long(Count)*(FRange-dbValue)/(FScaleTicks-1))+dbValue)/FRange)*20)
  1500.          end;
  1501.          if (FDirection = dirNormal) then
  1502.             Count := 0
  1503.          else
  1504.             Count := FSensitivy;
  1505.          if (FKind = lkHorizontal) then
  1506.             TextOut(MulDiv32(i,R.Right-R.Left-TextWidth(IntToStr(Count))-1,FScaleTicks-1),
  1507.                     R.Top + (R.Bottom-R.Top-TextHeight(IntToStr(Volume))) div 2,IntToStr(Volume))
  1508.          else
  1509.             TextOut(R.Left + (R.Right-R.Left-TextWidth(IntToStr(Volume))) div 2,
  1510.                     MulDiv32(i,R.Bottom-R.Top-TextHeight(IntToStr(Count))-1,FScaleTicks-1),
  1511.                     IntToStr(Volume));
  1512.       end;
  1513.    end;
  1514. end;
  1515. *)
  1516. { TODO: Not perfect yet ! }
  1517. {-- TMMLevelScale -------------------------------------------------------}
  1518. procedure TMMLevelScale.Paint;
  1519. Label NextLoop;
  1520. const
  1521.    FRange = $7FFF;
  1522. var
  1523.    i, j, Pos, H2, W2, th, tw, tw2, Count, CurValue, Volume: Longint;
  1524.    dbValue  : Float;
  1525.    R        : TRect;
  1526.    Rev      : Boolean;
  1527.    P1, P2   : Integer;
  1528.    Skip     : Integer;
  1529.    incValue : Integer;
  1530.    Offset   : Integer;
  1531.    s        : string;
  1532. begin
  1533.    with Canvas do
  1534.    begin
  1535.       Brush.Color := Color;
  1536.       FillRect(ClientRect);
  1537.       Font := Self.Font;
  1538.       R := ClientRect;
  1539.       if (Kind = lkHorizontal) then
  1540.          Offset := TextWidth('0') div 2
  1541.       else
  1542.          Offset := TextHeight('0') div 2;
  1543.       if Scale.Visible then
  1544.       begin
  1545.         Scale.Canvas := Canvas;
  1546.         Rev := (Kind = lkVertical) xor (Direction = dirReversed);
  1547.         if Rev then
  1548.         begin
  1549.             Scale.Color  := Scale3Color;
  1550.             Scale.Color2 := Scale2Color;
  1551.             Scale.Color3 := Scale1Color;
  1552.             P1           := 100 - Point2;
  1553.             P2           := 100 - Point1;
  1554.         end
  1555.         else
  1556.         begin
  1557.             Scale.Color  := Scale1Color;
  1558.             Scale.Color2 := Scale2Color;
  1559.             Scale.Color3 := Scale3Color;
  1560.             P1           := Point1;
  1561.             P2           := Point2;
  1562.         end;
  1563.         Scale.Point1 := MulDiv(P1-1,Scale.TickCount,100);
  1564.         Scale.Point2 := MulDiv(P2-1,Scale.TickCount,100);
  1565.         if (ScalePos = spAboveOrLeft) or (ScalePos = spBoth) then
  1566.         begin
  1567.            if Kind = lkHorizontal then
  1568.            begin
  1569.               if Direction <> dirReversed then
  1570.                  Scale.DrawRect(Canvas,Rect(R.Left-Offset-1,R.Top,R.Right-Offset-1,R.Top+Scale.ScaleHeight),True)
  1571.               else
  1572.                  Scale.DrawRect(Canvas,Rect(R.Left+Offset,R.Top,R.Right+Offset-1,R.Top+Scale.ScaleHeight),True);
  1573.               Inc(R.Top,Scale.ScaleHeight);
  1574.            end
  1575.            else
  1576.            begin
  1577.               if Direction <> dirReversed then
  1578.                  Scale.DrawRect(Canvas,Rect(R.Left,R.Top+Offset,R.Left+Scale.ScaleHeight,R.Bottom+Offset-1),True)
  1579.               else
  1580.                  Scale.DrawRect(Canvas,Rect(R.Left,R.Top-Offset,R.Left+Scale.ScaleHeight,R.Bottom-Offset-1),True);
  1581.               Inc(R.Left,Scale.ScaleHeight);
  1582.            end;
  1583.         end;
  1584.         if (ScalePos = spBelowOrRight) or (ScalePos = spBoth) then
  1585.         begin
  1586.            if Kind = lkHorizontal then
  1587.            begin
  1588.               if Direction <> dirReversed then
  1589.                  Scale.DrawRect(Canvas,Rect(R.Left-Offset-1,R.Bottom-Scale.ScaleHeight,R.Right-Offset-1,R.Bottom),False)
  1590.               else
  1591.                  Scale.DrawRect(Canvas,Rect(R.Left+Offset,R.Bottom-Scale.ScaleHeight,R.Right+Offset-1,R.Bottom),False);
  1592.               Dec(R.Bottom,Scale.ScaleHeight)
  1593.            end
  1594.            else
  1595.            begin
  1596.               if Direction <> dirReversed then
  1597.                  Scale.DrawRect(Canvas,Rect(R.Right-Scale.ScaleHeight,R.Top+Offset,R.Right,R.Bottom+Offset-1),False)
  1598.               else
  1599.                  Scale.DrawRect(Canvas,Rect(R.Right-Scale.ScaleHeight,R.Top-Offset,R.Right,R.Bottom-Offset-1),False);
  1600.               Dec(R.Right,Scale.ScaleHeight);
  1601.            end;
  1602.         end;
  1603.       end;
  1604.       if (R.Top > R.Bottom) or (R.Left > R.Right) then Exit;
  1605.       th := TextHeight('W');
  1606.       tw := TextWidth(IntToStr(FSensitivy));
  1607.       tw2:= tw;
  1608.       { maybe we must skip some ticks ? }
  1609.       Skip := 1;
  1610.       if (FKind = lkHorizontal) then
  1611.       begin
  1612.          if (Direction = dirSymetric) then
  1613.             while (Width div 2) div (((FScaleTicks-1) div skip)*tw) < 1 do inc(Skip)
  1614.          else
  1615.             while Width div (((FScaleTicks-1) div skip)*tw) < 1 do inc(Skip);
  1616.          if (Direction <> dirReversed) then
  1617.             incValue := -1
  1618.          else
  1619.             incValue := 1;
  1620.       end
  1621.       else
  1622.       begin
  1623.          if (Direction = dirSymetric) then
  1624.              while (Height div 2) div (((FScaleTicks-1) div skip)*th) < 1 do inc(Skip)
  1625.          else
  1626.              while Height div (((FScaleTicks-1) div skip)*th) < 1 do inc(Skip);
  1627.          if (Direction <> dirReversed) then
  1628.             incValue := 1
  1629.          else
  1630.             incValue := -1;
  1631.       end;
  1632.       if (incValue = 1) then
  1633.          i := 0
  1634.       else
  1635.          i := FScaleTicks-1;
  1636.       H2 := (R.Bottom-R.Top) div 2;
  1637.       W2 := (R.Right-R.Left) div 2;
  1638.       { draw the scale }
  1639.       for j := 0 to FScaleTicks-1 do
  1640.       begin
  1641.          if ((j) mod Skip <> 0) then goto NextLoop;
  1642.          CurValue := MulDiv(FRange,i,FScaleTicks-1);
  1643.          if ((FKind = lkHorizontal) and (FDirection = dirReversed)) or
  1644.             ((FKind = lkVertical) and (FDirection <> dirReversed)) then
  1645.             CurValue := FRange - CurValue;
  1646.          if (CurValue > Long(FPoint2)*FRange/100) then Font.Color := FScale3Color
  1647.          else if (CurValue > Long(FPoint1)*FRange/100) then Font.Color := FScale2Color
  1648.          else Font.Color := FScale1Color;
  1649.          if FLogAmp then
  1650.          begin
  1651.             Count := i;
  1652.             if ((FKind = lkHorizontal) and (FDirection <> dirReversed)) or
  1653.                ((FKind = lkVertical) and (FDirection = dirReversed)) then
  1654.                  Count := FScaleTicks-1-Count;
  1655.             Volume := Muldiv(Count,FSensitivy,FScaleTicks-1)
  1656.          end
  1657.          else
  1658.          begin
  1659.             Count := i;
  1660.             if ((FKind = lkHorizontal) and (FDirection = dirReversed)) or
  1661.                ((FKind = lkVertical) and (FDirection <> dirReversed)) then
  1662.                  Count := FScaleTicks-1-Count;
  1663.             dbValue := FRange/pow(10,-FSensitivy/20);
  1664.             Volume := Round(Log10(((Long(Count)*(FRange-dbValue)/(FScaleTicks-1))+dbValue)/FRange)*20)
  1665.          end;
  1666.          if (FKind = lkHorizontal) then
  1667.          begin
  1668.             s := IntToStr(Volume);
  1669.             tw := TextWidth(s);
  1670.             if (FDirection = dirSymetric) then
  1671.             begin
  1672.                Pos := MulDivRN(i,(R.Right-R.Left-1)div 2,FScaleTicks-1);
  1673.                if (Pos >= 0) and (W2-Pos+tw <= W2) then
  1674.                begin
  1675.                   TextOut(R.Left+Pos-(tw div 2),R.Top+(R.Bottom-R.Top-th)div 2,s);
  1676.                   if (i < FScaleTicks-1) then
  1677.                   begin
  1678.                      s := '+'+IntToStr(abs(Volume));
  1679.                      TextOut(R.Left+2*W2-Pos-1-(tw div 2),R.Top+(R.Bottom-R.Top-th)div 2,s);
  1680.                   end; 
  1681.                end;
  1682.             end
  1683.             else
  1684.             begin
  1685.                Pos := MulDivRN(i,R.Right-R.Left-1,FScaleTicks-1);
  1686.                if incValue = -1 then dec(Pos,tw);
  1687.                if (Pos >= 0) and (Pos+tw <= Width) then
  1688.                   TextOut(R.Left+Pos,R.Top+(R.Bottom-R.Top-th)div 2,s);
  1689.             end;
  1690.          end
  1691.          else
  1692.          begin
  1693.             s := IntToStr(Volume);
  1694.             tw := TextWidth(s);
  1695.             if (FDirection = dirSymetric) then
  1696.             begin
  1697.                Pos := MulDivRN(i,(R.Bottom-R.Top-1)div 2,FScaleTicks-1);
  1698.                if (Pos >= 0) and (Pos+th <= H2) then
  1699.                begin
  1700.                   TextOut(R.Right-(R.Right-R.Left)div 2 -(tw2 div 2)+(tw2-tw)-1,R.Top+H2+1+Pos-(th div 2),s);
  1701.                   if (i > 0) then
  1702.                   begin
  1703.                      s := '+'+IntToStr(abs(Volume));
  1704.                      TextOut(R.Right-(R.Right-R.Left)div 2 -(tw2 div 2)+(tw2-tw)-1,R.Top+H2+1-Pos-(th div 2),s);
  1705.                   end;
  1706.                end;
  1707.             end
  1708.             else
  1709.             begin
  1710.                Pos := MulDivRN(i,R.Bottom-R.Top-1,FScaleTicks-1);
  1711.                if incValue = -1 then dec(Pos,th);
  1712.                if (Pos >= 0) and (Pos+th <= Height) then
  1713.                    TextOut(R.Right-(R.Right-R.Left)div 2 -(tw2 div 2)+(tw2-tw)-1,R.Top+Pos,s);
  1714.             end;
  1715.          end;
  1716. NextLoop:
  1717.          i := i + incValue;
  1718.       end;
  1719.    end;
  1720. end;
  1721. end.