Flutter光谱分析插件spectrum_lib的使用
Flutter光谱分析插件spectrum_lib的使用
简介
spectrum_lib
是一个用于计算EEG信号频谱的数学库。其主要功能包括原始频谱值的计算以及EEG频谱值的计算。该库支持两种工作模式:迭代模式(添加新数据到内部缓冲区并计算频谱值)和一次性频谱计算模式(针对给定数组进行频谱计算)。在迭代模式下,频谱计算频率由初始化时设置的频率决定。
频谱通过FFT方法计算。可以单独计算任何信号的频谱,无论是原始信号还是经过滤波后的信号。
安装
支持平台
- Android
- iOS
- MacOS
- Windows
- Linux
使用Flutter安装
运行以下命令:
$ flutter pub add spectrum_lib
手动安装
- 在
pubspec.yaml
文件的依赖项中添加:dependencies: spectrum_lib: ^1.0.0
- 运行以下命令以获取依赖项:
$ flutter pub get
然后在Dart代码中导入:
import 'package:spectrum_lib/spectrum_lib.dart';
注意:此SDK需要蓝牙和位置权限,因此需要请求用户授权。
最新版本为 1.0.0
。
初始化
主要参数
- 原始信号采样频率。需要大于等于1。
- 频谱计算频率。需要小于等于16 kHz。
- 频谱计算窗口长度。需要小于等于信号采样频率。
可选参数
- 频率计算上限。默认值为采样率的一半。
- 是否对EEG频谱进行带宽归一化。默认禁用。
- α、β、θ、γ、δ波的权重系数。默认值为1.0。
创建实例
int samplingRate = 250; // 原始信号采样频率
int fftWindow = 1000; // 频谱计算窗口长度
int processWinRate = 5; // 频谱计算频率
final math = SpectrumLib(samplingRate, fftWindow, processWinRate);
可选初始化
添加额外频谱设置
int bordFrequency = 50; // 频率计算上限
bool normalizeSpectByBandwidth = true; // 是否对EEG频谱进行带宽归一化
math.initParams(bordFrequency, normalizeSpectByBandwidth);
设置波形系数
double deltaCoef = 0.0;
double thetaCoef = 1.0;
double alphaCoef = 1.0;
double betaCoef = 1.0;
double gammaCoef = 0.0;
math.setWavesCoeffs(deltaCoef, thetaCoef, alphaCoef, betaCoef, gammaCoef);
设置平滑窗口类型
math.setHammingWinSpectrum(); // 使用汉宁窗
math.setHanningWinSpectrum(); // 使用汉明窗
初始化数据数组
用于传递给库的数据数组应为双精度浮点数类型的数组,且长度不大于15倍的信号采样频率。
类型定义
RawSpectrumData
包含原始频谱值的结构体(带有边界频率)。
字段:
allBinsNums
: 整数值。FFT条数量。allBinsValues
: 双精度浮点数组。原始FFT条值。totalRawPow
: 双精度浮点值。总原始频谱功率。
WavesSpectrumData
包含波形值的结构体。
绝对频率值(双精度类型):
delta_raw
theta_raw
alpha_raw
beta_raw
gamma_raw
相对值(百分比)(双精度类型):
delta_rel
theta_rel
alpha_rel
beta_rel
gamma_rel
FFT频段分辨率
库会根据指定的窗口长度自动匹配最优的FFT缓冲区长度(2的幂)。获取FFT频段分辨率(每1Hz的FFT条数):
math.getFFTBinsFor1Hz();
迭代模式下的频谱计算
添加和处理数据
List<double> data = List.empty();
math.pushAndProcessData(data);
获取结果
List<RawSpectrumData> rawSpectrumData = math.readRawSpectrumInfoArr();
List<WavesSpectrumData> wavesSpectrumData = math.readWavesSpectrumInfoArr();
更新样本大小
math.setNewSampleSize();
单次数组的频谱计算
计算频谱
List<double> data = List.empty();
math.computeSpectrum(data);
获取结果
RawSpectrumData rawSpectrumData = math.readRawSpectrumInfo();
WavesSpectrumData wavesSpectrumData = math.readWavesSpectrumInfo();
结束与释放资源
math.dispose();
示例代码
以下是完整的示例代码:
import 'dart:ffi';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:spectrum_lib/spectrum_lib.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int samplingRate = 500;
int processWinRate = 2;
int fftWindow = 500 * 4;
late final SpectrumLib spectrumLib;
[@override](/user/override)
void initState() {
super.initState();
spectrumLib = SpectrumLib(samplingRate, fftWindow, processWinRate);
int bordFrequency = 30;
spectrumLib.initParams(bordFrequency, true);
}
[@override](/user/override)
void dispose() {
spectrumLib.dispose();
super.dispose();
}
void _onButtonPressed() {
double deltaCoef = 0.0;
double thetaCoef = 1.0;
double alphaCoef = 1.0;
double betaCoef = 1.0;
double gammaCoef = 0.0;
spectrumLib.setWavesCoeffs(deltaCoef, thetaCoef, alphaCoef, betaCoef, gammaCoef);
double nBinsFor1hz = spectrumLib.getFFTBinsFor1Hz();
int winLen = 500;
List<double> data = List.filled(winLen, 0.0);
for (var i = 0; i < 100; i++) {
for (int j = 0; j < 40; j++) {
for (int i = 0; i < winLen; i++) {
data[i] = 10 * sin(10 * i * (2 * pi / samplingRate));
}
spectrumLib.pushAndProcessData(data);
List<RawSpectrumData> rawSpectData = spectrumLib.readRawSpectrumInfoArr();
nBinsFor1hz = spectrumLib.getFFTBinsFor1Hz();
for (int i = 0; i < rawSpectData.length; i++) {
print("Bins: $nBinsFor1hz AllBinsValue: ${rawSpectData[i].allBinsValues.length} RawPow: ${rawSpectData[i].totalRawPow}");
}
spectrumLib.setNewSampleSize();
}
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('SpectrumLib example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _onButtonPressed,
child: const Text('Start Demo'),
),
],
),
),
),
);
}
}
更多关于Flutter光谱分析插件spectrum_lib的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter光谱分析插件spectrum_lib的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
spectrum_lib
是一个 Flutter 插件,用于在移动设备上进行光谱分析。这个插件通常用于处理音频信号,提取频率信息,并将其可视化为光谱图。以下是如何在 Flutter 项目中使用 spectrum_lib
的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 spectrum_lib
插件的依赖。
dependencies:
flutter:
sdk: flutter
spectrum_lib: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
来获取依赖。
2. 导入插件
在你的 Dart 文件中导入 spectrum_lib
。
import 'package:spectrum_lib/spectrum_lib.dart';
3. 初始化频谱分析器
你可以通过创建 SpectrumAnalyzer
的实例来初始化频谱分析器。
SpectrumAnalyzer spectrumAnalyzer = SpectrumAnalyzer();
4. 开始频谱分析
你可以使用 start
方法来开始频谱分析。通常,你需要提供一个音频源(例如麦克风输入或音频文件)作为输入。
spectrumAnalyzer.start();
5. 获取频谱数据
你可以通过监听 spectrumAnalyzer.onSpectrumData
来获取实时的频谱数据。
spectrumAnalyzer.onSpectrumData.listen((spectrumData) {
// 处理频谱数据
print(spectrumData);
});
6. 停止频谱分析
当你不再需要频谱分析时,可以调用 stop
方法来停止分析。
spectrumAnalyzer.stop();
7. 可视化频谱数据
你可以使用 Flutter 的绘图功能(如 CustomPaint
或第三方库如 fl_chart
)来将频谱数据可视化。
CustomPaint(
size: Size(double.infinity, 200),
painter: SpectrumPainter(spectrumData),
)
8. 处理权限
在 Android 和 iOS 上,你可能需要请求麦克风权限。你可以使用 permission_handler
插件来处理权限请求。
import 'package:permission_handler/permission_handler.dart';
void requestMicrophonePermission() async {
var status = await Permission.microphone.status;
if (!status.isGranted) {
await Permission.microphone.request();
}
}
9. 完整示例
以下是一个简单的完整示例,展示如何使用 spectrum_lib
进行频谱分析并将其可视化。
import 'package:flutter/material.dart';
import 'package:spectrum_lib/spectrum_lib.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: SpectrumScreen(),
);
}
}
class SpectrumScreen extends StatefulWidget {
[@override](/user/override)
_SpectrumScreenState createState() => _SpectrumScreenState();
}
class _SpectrumScreenState extends State<SpectrumScreen> {
SpectrumAnalyzer spectrumAnalyzer = SpectrumAnalyzer();
List<double> spectrumData = [];
[@override](/user/override)
void initState() {
super.initState();
requestMicrophonePermission();
startSpectrumAnalysis();
}
void requestMicrophonePermission() async {
var status = await Permission.microphone.status;
if (!status.isGranted) {
await Permission.microphone.request();
}
}
void startSpectrumAnalysis() {
spectrumAnalyzer.start();
spectrumAnalyzer.onSpectrumData.listen((data) {
setState(() {
spectrumData = data;
});
});
}
[@override](/user/override)
void dispose() {
spectrumAnalyzer.stop();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Spectrum Analyzer'),
),
body: Center(
child: CustomPaint(
size: Size(double.infinity, 200),
painter: SpectrumPainter(spectrumData),
),
),
);
}
}
class SpectrumPainter extends CustomPainter {
final List<double> spectrumData;
SpectrumPainter(this.spectrumData);
[@override](/user/override)
void paint(Canvas canvas, Size size) {
if (spectrumData.isEmpty) return;
final paint = Paint()
..color = Colors.blue
..strokeWidth = 2.0;
final barWidth = size.width / spectrumData.length;
for (int i = 0; i < spectrumData.length; i++) {
final barHeight = spectrumData[i] * size.height;
canvas.drawRect(
Rect.fromLTWH(
i * barWidth,
size.height - barHeight,
barWidth,
barHeight,
),
paint,
);
}
}
[@override](/user/override)
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}