Flutter信号处理插件smart_signal_processing的使用

Smart Signal Processing

这个插件能为你做什么?

该插件提供了信号处理中常用的函数:

  • 计算均值、方差和标准差。
  • 对数组应用窗口函数(窗函数),例如指数或高斯形状。
  • 对数组应用快速傅里叶变换(FFT)。
  • 计算复数数组的功率或幅值。
  • 对复数数组进行相位旋转(在复平面上旋转)。

示例

你可以直接通过以下链接运行示例代码:

或者下载插件并在浏览器中运行以下文件:

example/example.html

插件的主要API功能

该插件包含以下主要类:

  • Sigma:用于计算统计量。
  • BaseLine:用于基线校正。
  • WinFunc:用于窗口函数。
  • FFT:用于快速傅里叶变换。
  • Phase:用于计算相位。

示例代码片段

// 应用指数衰减
WinFunc.expMult(array, decayFactor, false, "0");

// 计算傅里叶变换
FFT.transform(reals, imags);

// 计算幅值
Phase.magnitude(reals, imags, true);

// 计算特定区域的方差
Sigma.variance(array, ixstart, ixend);

完整示例代码

以下是一个完整的示例代码,展示如何使用 smart_signal_processing 插件来生成一个衰减的余弦波,并对其进行傅里叶变换。

// Copyright (c) 2019, Dr. Bruno Guigas. All rights reserved. Use of this source
// code is governed by a BSD-style license that can be found in the LICENSE file.
import 'dart:html';
import 'dart:typed_data';
import 'dart:convert';
import 'dart:math' as math;

import 'package:smart_arrays_plot_polyline/smart_arrays_plot_polyline.dart';
import 'package:smart_arrays_sample_data/smart_arrays_sample_data.dart';
import 'package:smart_signal_processing/smart_signal_processing.dart';

/// Signal processing example:
/// - Computes NPERIODS periods of a cosine shape with NPOINTS data points.
/// - Applies an exponential function, resulting in a decaying oscillation.
/// - Applies a real Fourier transform, resulting in a complex-valued line shape
///   whose real part is an absorption mode Lorentzian, and whose imaginary
///   part is a dispersion mode Lorentzian. The real part's maximum is at the
///   index defined by the number of cosine periods (NPERIODS).
/// - Plots the real and imaginary parts and the cosine in the browser.
main() {
  // 生成一个余弦波
  Sine1D sine1d = Sine1D(NPOINTS, 100.0, math.pi / 2, NPERIODS, 0.0, 0.0);
  Float64List reals = sine1d.array;
  Float64List imags = Float64List(reals.length); // 原始为零

  // 使余弦波呈指数衰减
  double decayFactor = -3.0 / (reals.length - 1);
  WinFunc.expMult(reals, decayFactor, false, "0");
  Float64List decayingCosine = Float64List.fromList(reals); // 保存以供绘图

  // 在原地进行傅里叶变换:初始时 [imags] 全为零。变换后,
  // [reals] 包含吸收模式的洛伦兹线型,[imags] 包含分散模式的洛伦兹线型。
  FFT.transform(reals, imags);

  // 绘制结果:由于FFT的对称性,只绘制前半部分。
  // 第二部分包含相同的信息(对应于“负频率”)。为了使x轴适用于所有三条曲线,
  // 只绘制余弦波的一半。
  plotArrays([
    reals.sublist(0, reals.length ~/ 2), // 实部
    imags.sublist(0, imags.length ~/ 2), // 虚部
    decayingCosine.sublist(0, decayingCosine.length ~/ 2), // 衰减的余弦波
  ]);
}

final int NPOINTS = 512, NPERIODS = 50;

/// 显示由 [main] 计算的数组 [arrays],使用包 'smart_arrays_plot_polyline' 在浏览器中绘制。
void plotArrays(List<Float64List> arrays) {
  // 获取来自 'example.html' 的 div 容器
  DivElement appDiv = (querySelector("#app_div") as DivElement);
  DivElement plotDiv = (querySelector("#plot_div") as DivElement);

  // 设置绘图区域大小
  plotDiv.style
    ..width = "${appDiv.clientWidth}px"
    ..height = "${appDiv.clientHeight}px";

  // 设置折线图属性
  List<Map<PyA, String>> plotAttr = [
    {PyA.YPOSITION_ZERO: "0.6"}, // 实部位置
    {PyA.YPOSITION_ZERO: "0.6"}, // 虚部位置
    {PyA.YPOSITION_ZERO: "0.895", PyA.YSCALE: "5"} // 缩放并下移余弦波
  ];

  // 设置x轴标签
  Map<AxA, String> xaxisAttr = {
    AxA.PHYS_X_START: "0",
    AxA.PHYS_X_WIDTH: "${arrays[0].length}", // 来自实部
    AxA.LEGENDTEXT: "Number of points"
  };

  // 设置y轴标签
  Map<AxA, String> yaxisAttr = {AxA.LEGENDTEXT: "Relative units"};

  // 设置图例文本和位置
  Map<LegA, String> legendAttr = {
    LegA.TOP_TITLE:
        "Fourier Transform of a decaying cosine with $NPERIODS periods",
    LegA.SUB_TITLES: json.encode([
      "Real part after transform",
      "Imaginary part after transform",
      "Decaying cosine (first half, vertically expanded and shifted down)"
    ]),
    LegA.X: "45",
    LegA.Y: "15"
  };

  // 将数组绘制到 [plotDiv]
  SimplePlot(arrays, plotDiv, plotAttr, xaxisAttr, yaxisAttr, legendAttr, null);
}

更多关于Flutter信号处理插件smart_signal_processing的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter信号处理插件smart_signal_processing的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


smart_signal_processing 是一个用于 Flutter 的信号处理插件,它可以帮助你在 Flutter 应用中执行各种信号处理任务,如滤波、傅里叶变换、信号生成等。以下是如何在 Flutter 项目中使用 smart_signal_processing 插件的基本步骤。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 smart_signal_processing 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  smart_signal_processing: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入 smart_signal_processing 插件。

import 'package:smart_signal_processing/smart_signal_processing.dart';

3. 使用插件功能

smart_signal_processing 插件提供了多种信号处理功能。以下是一些常见的使用示例。

3.1 信号生成

你可以使用插件生成各种信号,如正弦波、方波等。

void generateSignal() {
  // 生成一个正弦波信号
  List<double> sineWave = SmartSignalProcessing.generateSineWave(
    frequency: 440.0,  // 频率
    amplitude: 1.0,    // 振幅
    sampleRate: 44100, // 采样率
    duration: 1.0,     // 持续时间(秒)
  );

  print(sineWave);
}

3.2 傅里叶变换

你可以使用插件对信号进行傅里叶变换。

void performFFT() {
  List<double> signal = [1.0, 0.0, -1.0, 0.0];  // 示例信号

  // 执行傅里叶变换
  List<Complex> fftResult = SmartSignalProcessing.fft(signal);

  print(fftResult);
}

3.3 滤波

你可以使用插件对信号进行滤波。

void applyFilter() {
  List<double> signal = [1.0, 2.0, 3.0, 4.0, 5.0];  // 示例信号

  // 应用低通滤波器
  List<double> filteredSignal = SmartSignalProcessing.lowPassFilter(
    signal: signal,
    cutoffFrequency: 0.1,  // 截止频率
    sampleRate: 44100,     // 采样率
  );

  print(filteredSignal);
}

4. 处理结果

你可以将处理后的信号用于进一步的分析、可视化或播放。

5. 示例应用

以下是一个简单的 Flutter 应用示例,展示了如何使用 smart_signal_processing 插件生成信号并显示其波形。

import 'package:flutter/material.dart';
import 'package:smart_signal_processing/smart_signal_processing.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SignalProcessingDemo(),
    );
  }
}

class SignalProcessingDemo extends StatefulWidget {
  [@override](/user/override)
  _SignalProcessingDemoState createState() => _SignalProcessingDemoState();
}

class _SignalProcessingDemoState extends State<SignalProcessingDemo> {
  List<double> signal = [];

  [@override](/user/override)
  void initState() {
    super.initState();
    generateSignal();
  }

  void generateSignal() {
    setState(() {
      signal = SmartSignalProcessing.generateSineWave(
        frequency: 440.0,
        amplitude: 1.0,
        sampleRate: 44100,
        duration: 1.0,
      );
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Signal Processing Demo'),
      ),
      body: Center(
        child: CustomPaint(
          size: Size(300, 150),
          painter: SignalPainter(signal),
        ),
      ),
    );
  }
}

class SignalPainter extends CustomPainter {
  final List<double> signal;

  SignalPainter(this.signal);

  [@override](/user/override)
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;

    final path = Path();
    final xStep = size.width / (signal.length - 1);

    for (int i = 0; i < signal.length; i++) {
      final x = i * xStep;
      final y = size.height / 2 - signal[i] * size.height / 4;
      if (i == 0) {
        path.moveTo(x, y);
      } else {
        path.lineTo(x, y);
      }
    }

    canvas.drawPath(path, paint);
  }

  [@override](/user/override)
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
回到顶部