Example #1
0
            public DrawHandler(WindowGraphics windowGraphics)
            {
                this.windowGraphics = windowGraphics;
                windowGraphics.TryUpdateGraphics();
                DrawingContext = windowGraphics.drawingVisual.RenderOpen();
                var transformGroup = new TransformGroup();

                transformGroup.Children.Add(new ScaleTransform(1, -1));
                transformGroup.Children.Add(new TranslateTransform(0, windowGraphics.height));
                transformGroup.Freeze();
                DrawingContext.PushTransform(transformGroup);
            }
Example #2
0
        /// <summary>
        /// 绘制波形
        /// </summary>
        /// <param name="win"></param>
        /// <param name="waveQueueData"></param>
        /// <param name="polylineStyle"></param>
        /// <param name="id">区分线程,调试用</param>
        static void DrawWave(Window win, FixedQueueArray <float> waveQueueData, bool polylineStyle, int id = 0)
        {
            var lineColor = Color.FromRgb(17, 125, 187);
            var lineBrush = new SolidColorBrush(lineColor);

            lineBrush.Freeze();
            var pen = new Pen(lineBrush, 1);

            pen.Freeze();

            // WindowGraphics 这是一个可以跨进程绘制窗体的类
            // 使用 WPF 中的 DrawingContext 进行绘制
            var wg = new WindowGraphics(win);

            while (true)
            {
                Task.Delay(20).Wait();

                using (var drawCtx = wg.OpenDraw()) {
                    Span <float> waveData = new float[(int)drawCtx.Size.Width];
                    waveQueueData.Read(waveData);

                    drawCtx.DrawingContext.DrawRectangle(Brushes.White, null, new Rect(drawCtx.Size));
                    DrawBorder(drawCtx);

                    var     h2 = drawCtx.Size.Height / 2;
                    Point[] points;
                    if (polylineStyle)
                    {
                        const int step = 10;
                        points = new Point[waveData.Length / step + 1];
                        for (int i = 0; i < points.Length; i++)
                        {
                            double sum   = 0;
                            int    count = 0;
                            for (int j = 0; j < step; j++)
                            {
                                if (i * step + j >= waveData.Length)
                                {
                                    break;
                                }
                                sum += waveData[i * step + j];
                                count++;
                            }
                            var avg = count > 0 ? sum / count : 0;
                            points[i] = new Point(i * step, h2 + avg * h2);
                        }
                        points[points.Length - 1].X = drawCtx.Size.Width;
                    }
                    else
                    {
                        points = new Point[waveData.Length];
                        for (int i = 0; i < waveData.Length; i++)
                        {
                            double y = waveData[i] * h2;
                            points[i] = new Point(i, h2 + y);
                        }
                    }

                    var geometry = new StreamGeometry();
                    using (var geometryCtx = geometry.Open()) {
                        geometryCtx.BeginFigure(points[0], false, false);
                        geometryCtx.PolyLineTo(points, true, true);
                    }
                    geometry.Freeze();
                    drawCtx.DrawingContext.DrawGeometry(null, pen, geometry);
                }
            }
        }
Example #3
0
        /// <summary>
        /// 绘制频谱(FFT算法用的是FFTW库)
        /// </summary>
        /// <param name="win"></param>
        /// <param name="nextData"></param>
        /// <param name="sampleRate"></param>
        /// <param name="polylineStyle"></param>
        /// <param name="id">区分线程,调试用</param>
        static void DrawSpectrum(Window win, float[] nextData, int sampleRate, bool polylineStyle, int id = 0)
        {
            double *      inBuff    = (double *)fftw.alloc_complex((IntPtr)FFTSize);
            double *      outBuff   = (double *)fftw.alloc_complex((IntPtr)FFTSize);
            IntPtr        fft       = fftw.dft_1d(FFTSize, (IntPtr)inBuff, (IntPtr)outBuff, fftw_direction.Forward, fftw_flags.Estimate);
            Span <double> tempBuff  = stackalloc double[FFTSize];
            var           cutLength = FFTTools.CutFrequencyLength(FFTSize, MinimumFrequency, MaximumFrequency, sampleRate, FFTComplexCount);
            Span <double> cutData   = tempBuff.Slice(0, cutLength);

            DSP.Window fftWindow = new DSP.BlackmanNuttallWindow(FFTSize);
            ILogarithm log       = new DSP.Decade();
            var        lineBrush = new SolidColorBrush(Color.FromRgb(17, 125, 187));
            var        pen       = new Pen(lineBrush, 1);
            var        backBrush = new SolidColorBrush(Color.FromRgb(241, 246, 250));

            lineBrush.Freeze();
            pen.Freeze();
            backBrush.Freeze();
            Point[] drawPoints = null;

            Span <double> logData = null;
            var           wg      = new WindowGraphics(win);

            while (true)
            {
                Task.Delay(20).Wait();

                using (var drawCtx = wg.OpenDraw()) {
                    lock (fftLock) {
                        for (int i = 0; i < nextData.Length; i++)
                        {
                            tempBuff[i] = nextData[i];
                        }
                    }
                    // 加窗
                    fftWindow?.Apply(tempBuff, tempBuff);
                    for (int i = 0; i < tempBuff.Length; i++)
                    {
                        inBuff[2 * i + 0] = tempBuff[i];
                        inBuff[2 * i + 1] = 0;
                    }
                    // 执行FFT
                    fftw.execute(fft);

                    if (logData == null || logData.Length != (int)drawCtx.Size.Width)
                    {
                        logData = new double[(int)drawCtx.Size.Width];
                    }
                    double h = drawCtx.Size.Height;
                    // FFT复数结果取模
                    FFTTools.Abs(FFTSize, new ReadOnlySpan <Complex>(outBuff, FFTSize), tempBuff, true, fftWindow);
                    // 保留感兴趣的频率区域
                    FFTTools.CutFrequency(FFTSize, MinimumFrequency, MaximumFrequency, sampleRate, tempBuff, cutData);
                    // 频率以对数方式显示
                    FFTTools.Logarithm(cutData, MinimumFrequency, MaximumFrequency, logData, log);
                    // 振幅以分贝方式显示
                    FFTTools.ToDB(logData, MaxDB);
                    // 因为上面的结果在区间[0,1],所以乘以窗体高度h,才能画满整个窗体
                    FFTTools.Scale(logData, h);

                    if (polylineStyle)
                    {
                        const int step   = 10;
                        var       points = new Point[logData.Length / step + 1];
                        for (int i = 0; i < points.Length; i++)
                        {
                            double max = 0;
                            for (int j = 0; j < step; j++)
                            {
                                if (i * step + j >= logData.Length)
                                {
                                    break;
                                }
                                max = Math.Max(logData[i * step + j], max);
                            }
                            points[i] = new Point(i * step, h - max);
                        }
                        points[points.Length - 1].X = drawCtx.Size.Width;

                        drawPoints = new Point[points.Length + 2];
                        points.AsSpan().CopyTo(drawPoints);
                    }
                    else
                    {
                        drawPoints = new Point[logData.Length + 2];
                        for (int i = 0; i < logData.Length; i++)
                        {
                            drawPoints[i] = new Point(i, h - logData[i]);
                        }
                    }

                    drawPoints[drawPoints.Length - 2] = new Point(drawCtx.Size.Width, drawCtx.Size.Height);
                    drawPoints[drawPoints.Length - 1] = new Point(0, drawCtx.Size.Height);

                    var geometry = new StreamGeometry();
                    using (var geometryCtx = geometry.Open()) {
                        geometryCtx.BeginFigure(drawPoints[0], true, true);
                        geometryCtx.PolyLineTo(drawPoints, true, true);
                    }
                    geometry.Freeze();

                    drawCtx.DrawingContext.DrawRectangle(Brushes.White, null, new Rect(drawCtx.Size));
                    drawCtx.DrawingContext.DrawGeometry(backBrush, null, geometry);
                    DrawBorder(drawCtx);
                    drawCtx.DrawingContext.DrawGeometry(null, pen, geometry);
                }
            }
        }