public void ProcessData(byte[] dataBuffer)
        {
            const int bytePerSample = 2;
            const int channels      = 2;

            if (FFTDisplay.EnoughData && WaterfallDisplay.EnoughData)
            {
                return;
            }

            lock (FFTLock)
            {
                int samplePairs = dataBuffer.Length / (channels * bytePerSample);

                for (int samplePair = 0; samplePair < samplePairs; samplePair++)
                {
                    int    samplePairPos = samplePair * bytePerSample * channels;
                    double I             = ByteUtil.getDoubleFromBytes(dataBuffer, samplePairPos);
                    double Q             = ByteUtil.getDoubleFromBytes(dataBuffer, samplePairPos + bytePerSample);


                    FFT.AddSample(I, Q);

                    if (FFT.ResultAvailable)
                    {
                        FFT.GetResultSquared(FFTResult);

                        FFTDisplay.ProcessFFTData(FFTResult);
                        WaterfallDisplay.ProcessFFTData(FFTResult);
                    }
                }
            }
        }
 public void FocusHovered()
 {
     if (WaterfallDisplay.MouseHovering)
     {
         WaterfallDisplay.Focus();
     }
     if (FFTDisplay.MouseHovering)
     {
         FFTDisplay.Focus();
     }
 }
        public void ProcessData(double[] iSamples, double[] qSamples, int spectPart, double baseAmp)
        {
            FpsBlocksReceived++;

            /* TODO: waterfall display sometimes holds "EnoughData" and doesnt reset */
            if (FFTDisplay.EnoughData && WaterfallDisplay.EnoughData)
            {
                return;
            }

            FpsBlocksProcessed++;

            lock (FFTLock)
            {
                int samplePairs = iSamples.Length;

                for (int samplePair = 0; samplePair < samplePairs; samplePair++)
                {
                    double I = iSamples[samplePair];
                    double Q = qSamples[samplePair];

                    FFT.AddSample(I, Q);

                    if (FFT.ResultAvailable)
                    {
                        FFT.GetResultSquared(FFTResult);

                        ReceiverCorrection.ApplyCorrectionTable(FFTResult);
                        FilterCorrection.ApplyCorrectionTable(FFTResult);

                        Remote.ProcessData(FFTResult);

                        if (FitSpectrumEnabled)
                        {
                            CenterCut((int)(FitSpectrumWidth * FFTSize));
                            FFTDisplay.ProcessFFTData(FFTResultPartial, spectPart, baseAmp);
                            WaterfallDisplay.ProcessFFTData(FFTResultPartial, spectPart, baseAmp);
                        }
                        else
                        {
                            FFTDisplay.ProcessFFTData(FFTResult, spectPart, baseAmp);
                            WaterfallDisplay.ProcessFFTData(FFTResult, spectPart, baseAmp);
                        }
                    }
                }
            }
        }
        public void ProcessSample(double I, double Q, int spectPart, int spectParts, double baseAmp)
        {
            lock (FFTLock)
            {
                FFT.AddSample(I, Q);

                if (FFT.ResultAvailable)
                {
                    FFT.GetResultSquared(FFTResult);

                    ReceiverCorrection.ApplyCorrectionTable(FFTResult);
                    FilterCorrection.ApplyCorrectionTable(FFTResult);

                    FFTDisplay.ProcessFFTData(FFTResult, spectPart, baseAmp);
                    WaterfallDisplay.ProcessFFTData(FFTResult, spectPart, baseAmp);
                }
            }
        }
        public void UserEventCallbackFunc(eUserEvent evt, double param)
        {
            switch (evt)
            {
            case eUserEvent.MouseEnter:
                FFTDisplay.ShowVerticalCursor       = true;
                WaterfallDisplay.ShowVerticalCursor = true;

                UserEventCallbackFunc(eUserEvent.StatusUpdated, 0);
                break;

            case eUserEvent.MouseLeave:
                WaterfallDisplay.LevelBarActive = false;

                FFTDisplay.MainText       = "";
                WaterfallDisplay.MainText = "";

                FFTDisplay.ShowVerticalCursor       = false;
                WaterfallDisplay.ShowVerticalCursor = false;

                UserEventCallbackFunc(eUserEvent.StatusUpdated, 0);
                break;

            /* used to paint waterfall level bars */
            case eUserEvent.StatusUpdated:
                /* level bars toggled off */
                if (!WaterfallDisplay.LevelBarActive && LevelBarActive)
                {
                    FFTDisplay.LabelledHorLines.Remove(LevelBarLower);
                    if (!WaterfallDisplay.DynamicLimits)
                    {
                        FFTDisplay.LabelledHorLines.Remove(LevelBarUpper);
                    }
                    LevelBarActive = false;
                }

                /* level bars toggled on */
                if (WaterfallDisplay.LevelBarActive && !LevelBarActive)
                {
                    FFTDisplay.LabelledHorLines.AddLast(LevelBarLower);
                    if (!WaterfallDisplay.DynamicLimits)
                    {
                        FFTDisplay.LabelledHorLines.AddLast(LevelBarUpper);
                    }
                    LevelBarActive = true;
                }

                if (!WaterfallDisplay.DynamicLimits)
                {
                    LevelBarLower.Position = WaterfallDisplay.LeveldBBlack;
                    LevelBarUpper.Position = WaterfallDisplay.LeveldBWhite;
                }
                else
                {
                    LevelBarLower.Position = WaterfallDisplay.LeveldBBlack;
                }
                FFTDisplay.UpdateOverlays    = true;
                FFTDisplay.NeedsRender       = true;
                WaterfallDisplay.NeedsRender = true;
                break;

            case eUserEvent.MouseWheelUp:
                FFTDisplay.ProcessUserAction(eUserAction.YZoomIn, param);
                break;

            case eUserEvent.MouseWheelDown:
                FFTDisplay.ProcessUserAction(eUserAction.YZoomOut, param);
                break;


            case eUserEvent.MousePosX:
                FFTDisplay.ProcessUserAction(eUserAction.XPos, param);
                WaterfallDisplay.ProcessUserAction(eUserAction.XPos, param);
                break;

            case eUserEvent.MouseDragXShift:
                FFTDisplay.ProcessUserAction(eUserAction.XOffsetOverview, param);
                WaterfallDisplay.ProcessUserAction(eUserAction.XOffsetOverview, param);
                break;

            case eUserEvent.MouseDragX:
                FFTDisplay.ProcessUserAction(eUserAction.XOffset, param);
                WaterfallDisplay.ProcessUserAction(eUserAction.XOffset, param);
                break;

            case eUserEvent.MouseWheelUpShift:
                FFTDisplay.ProcessUserAction(eUserAction.XZoomIn, param);
                WaterfallDisplay.ProcessUserAction(eUserAction.XZoomIn, param);
                break;

            case eUserEvent.MouseWheelDownShift:
                FFTDisplay.ProcessUserAction(eUserAction.XZoomOut, param);
                WaterfallDisplay.ProcessUserAction(eUserAction.XZoomOut, param);
                break;

                /*
                 * case eUserEvent.MouseWheelUpAlt:
                 * if (WaterfallDisplay.UpdateRate < 512)
                 * {
                 *  FFTDisplay.UpdateRate *= 2;
                 *  WaterfallDisplay.UpdateRate *= 2;
                 * }
                 * break;
                 *
                 * case eUserEvent.MouseWheelDownAlt:
                 * if (WaterfallDisplay.UpdateRate > 1)
                 * {
                 *  FFTDisplay.UpdateRate /= 2;
                 *  WaterfallDisplay.UpdateRate /= 2;
                 * }
                 * break;
                 * */
            }

            /* finally inform master form about the event */
            if (UserEventCallback != null)
            {
                UserEventCallback(evt, param);
            }
        }