flutter如何实现录音并显示fft动画
在Flutter中如何实现录音功能并实时显示FFT频谱动画?目前我已经尝试使用audioplayers和sound_stream插件进行录音,但无法获取到音频的原始数据用于FFT计算。请问有哪些推荐的方法或插件可以同时实现录音和频谱分析?最好能够提供具体的代码示例或实现思路,特别是在处理实时音频数据和可视化方面的方案。
2 回复
在Flutter中实现录音并显示FFT动画,可以通过以下步骤完成:
1. 添加依赖
在 pubspec.yaml 中添加:
dependencies:
flutter_sound: ^X.X.X # 录音
mic_stream: ^X.X.X # 实时音频流
charts_flutter: ^X.X.X # 图表显示(可选)
运行 flutter pub get。
2. 录音和FFT处理
使用 mic_stream 获取实时音频数据,进行FFT计算:
import 'dart:math';
import 'package:mic_stream/mic_stream.dart';
class AudioRecorder {
Stream<List<int>>? _audioStream;
void startRecording() {
_audioStream = MicStream.microphone(
sampleRate: 44100,
audioFormat: AudioFormat.PCM_16BIT,
);
}
List<double> computeFFT(List<int> audioData) {
// 转换为浮点数
List<double> samples = audioData.map((e) => e.toDouble()).toList();
// 应用窗函数(例如汉宁窗)
for (int i = 0; i < samples.length; i++) {
samples[i] *= 0.5 * (1 - cos(2 * pi * i / (samples.length - 1)));
}
// 执行FFT(简化版,实际需使用完整FFT算法)
List<double> fftResult = [];
for (int k = 0; k < samples.length ~/ 2; k++) {
double real = 0.0;
double imag = 0.0;
for (int n = 0; n < samples.length; n++) {
real += samples[n] * cos(2 * pi * k * n / samples.length);
imag -= samples[n] * sin(2 * pi * k * n / samples.length);
}
fftResult.add(sqrt(real * real + imag * imag));
}
return fftResult;
}
}
3. 构建动画UI
使用 StreamBuilder 实时更新波形:
import 'package:flutter/material.dart';
class FFTScreen extends StatefulWidget {
@override
_FFTScreenState createState() => _FFTScreenState();
}
class _FFTScreenState extends State<FFTScreen> {
final AudioRecorder _recorder = AudioRecorder();
@override
void initState() {
super.initState();
_recorder.startRecording();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<List<int>>(
stream: _recorder._audioStream,
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
List<double> fftData = _recorder.computeFFT(snapshot.data!);
return CustomPaint(
painter: FFTPainter(fftData),
size: Size.infinite,
);
},
),
);
}
}
class FFTPainter extends CustomPainter {
final List<double> fftData;
FFTPainter(this.fftData);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 2.0;
double width = size.width / fftData.length;
for (int i = 0; i < fftData.length; i++) {
double x = i * width;
double height = fftData[i] * 100; // 缩放系数
canvas.drawLine(
Offset(x, size.height),
Offset(x, size.height - height),
paint,
);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
4. 权限配置
Android:在 AndroidManifest.xml 添加:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
iOS:在 Info.plist 添加:
<key>NSMicrophoneUsageDescription</key>
<string>需要麦克风权限进行录音</string>
注意事项:
- 实际FFT计算建议使用
fft包(如dart:math复数计算或第三方库) - 调整采样率和缓冲区大小平衡性能
- 使用
AnimationController可实现更流畅的动画效果
此方案提供了基础实现框架,可根据需求优化FFT算法和可视化效果。


