Flutter音频播放插件raw_sound的使用
Flutter音频播放插件raw_sound的使用
A flutter plugin for playing raw PCM audio data (16-bit integer and 32-bit float).
平台支持
Android (Kotlin) | iOS (Swift) |
---|---|
minSdkVersion 24 | platform :ios, ‘14.0’ |
✔️ | ✔️ |
使用
创建一个RawSoundPlayer实例
final _player = RawSoundPlayer();
初始化播放器实例
await _player.initialize(
// 缓冲区大小(仅适用于Android)
bufferSize: 4096 << 3,
// 声道数量,可以是1或2
nChannels: 1,
// 播放速率(Hz)
sampleRate: 16000,
// PCM格式类型,可以是PCMI16(16位整数)或PCMF32(32位浮点数)
pcmType: RawSoundPCMType.PCMI16,
);
开始播放
await _player.play();
向播放器实例喂入原始PCM数据
// 展示如何持续向播放器喂入数据直到播放暂停/停止
while (_player.isPlaying) {
await _player.feed(dataBlock);
}
暂停播放
// 立即暂停并保持队列中的缓冲区
await _player.pause();
停止播放
// 立即停止并丢弃队列中的缓冲区
await _player.stop();
释放播放器实例
// 记住要释放任何已初始化的播放器实例
await _player.release();
完整示例代码
以下是一个完整的示例代码,展示了如何使用raw_sound
插件播放16位整数和32位浮点数的PCM音频数据。
import 'dart:typed_data'; // for Uint8List
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:raw_sound/raw_sound_player.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// 缓冲区大小(仅适用于Android)
static int bufferSize = 4096 << 4;
// 声道数量,可以是1或2
static int nChannels = 1;
// 播放速率(Hz)
static int sampleRate = 16000;
// 频率(Hz)
static double freq = 440.0;
// 周期(秒)
static double period = 1.0 / freq;
// 音量(范围在0.0到1.0之间)
static double volume = 0.5;
// 用于播放16位整数PCM音频数据的播放器实例
final _playerPCMI16 = RawSoundPlayer();
// 用于播放32位浮点数PCM音频数据的播放器实例
final _playerPCMF32 = RawSoundPlayer();
[@override](/user/override)
void initState() {
super.initState();
// 初始化播放器实例
_playerPCMI16
.initialize(
bufferSize: bufferSize,
nChannels: nChannels,
sampleRate: sampleRate,
pcmType: RawSoundPCMType.PCMI16,
)
.then((value) {
setState(() {});
});
_playerPCMF32
.initialize(
bufferSize: bufferSize,
nChannels: nChannels,
sampleRate: sampleRate,
pcmType: RawSoundPCMType.PCMF32,
)
.then((value) {
setState(() {});
});
}
[@override](/user/override)
void dispose() {
// 释放播放器实例
_playerPCMI16.release();
_playerPCMF32.release();
super.dispose();
}
Future<void> _playPCMI16() async {
if (_playerPCMI16.isPlaying) {
return;
}
await _playerPCMI16.play();
setState(() {});
// 持续向播放器喂入数据直到播放暂停/停止
final dataBlock = _genPCMI16DataBlock(nPeriods: 20);
while (_playerPCMI16.isPlaying) {
await _playerPCMI16.feed(dataBlock);
}
}
Future<void> _pausePCMI16() async {
await _playerPCMI16.pause();
setState(() {});
}
Future<void> _playPCMF32() async {
if (_playerPCMF32.isPlaying) {
return;
}
await _playerPCMF32.play();
setState(() {});
// 持续向播放器喂入数据直到播放暂停/停止
final dataBlock = _genPCMF32DataBlock(nPeriods: 20);
while (_playerPCMF32.isPlaying) {
await _playerPCMF32.feed(dataBlock);
}
}
Future<void> _pausePCMF32() async {
await _playerPCMF32.pause();
setState(() {});
}
// 生成16位整数PCM音频数据
Uint8List _genPCMI16DataBlock({int nPeriods = 1}) {
final nFramesPerPeriod = (period * sampleRate).toInt();
debugPrint('nFrames / period: $nFramesPerPeriod');
final step = math.pi * 2 / nFramesPerPeriod;
// 填充一个周期的数据块
final dataBlockPerPeriod =
ByteData(nFramesPerPeriod << 1 /* one int16 is made of 2 bytes */);
for (int i = 0; i < nFramesPerPeriod; i++) {
// 幅度在-32767到32767之间
final value = (math.sin(step * i) * volume * 32767).toInt();
dataBlockPerPeriod.setInt16(
i << 1, value, Endian.host /* native endianness */);
}
// 重复数据块nPeriods次
final dataBlock = [];
for (int i = 0; i < nPeriods; i++) {
dataBlock.addAll(dataBlockPerPeriod.buffer.asUint8List());
}
debugPrint('dataBlock nBytes: ${dataBlock.length}');
return Uint8List.fromList(dataBlock);
}
// 生成32位浮点数PCM音频数据
Uint8List _genPCMF32DataBlock({int nPeriods = 1}) {
final nFramesPerPeriod = (period * sampleRate).toInt();
debugPrint('nFrames / period: $nFramesPerPeriod');
final step = math.pi * 2 / nFramesPerPeriod;
// 填充一个周期的数据块
final dataBlockPerPeriod =
ByteData(nFramesPerPeriod << 2 /* one float32 is made of 4 bytes */);
for (int i = 0; i < nFramesPerPeriod; i++) {
// 幅度在-1.0到1.0之间
final value = math.sin(step * i) * volume;
dataBlockPerPeriod.setFloat32(
i << 2, value, Endian.host /* native endianness */);
}
// 重复数据块nPeriods次
final dataBlock = [];
for (int i = 0; i < nPeriods; i++) {
dataBlock.addAll(dataBlockPerPeriod.buffer.asUint8List());
}
debugPrint('dataBlock nBytes: ${dataBlock.length}');
return Uint8List.fromList(dataBlock);
}
Widget build(BuildContext context) {
debugPrint('PlayerPCMI16 is inited? ${_playerPCMI16.isInited}');
debugPrint('PlayerPCMF32 is inited? ${_playerPCMF32.isInited}');
if (!_playerPCMI16.isInited || !_playerPCMF32.isInited) {
return Container();
}
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Raw Sound Plugin Example App'),
),
body: Column(
children: [
Card(
child: Row(
children: [
IconButton(
icon: Icon(_playerPCMI16.isPlaying
? Icons.stop
: Icons.play_arrow),
onPressed: () {
_playerPCMI16.isPlaying ? _pausePCMI16() : _playPCMI16();
},
),
Text('测试16位整数(PCMI16)'),
],
),
),
Card(
child: Row(
children: [
IconButton(
icon: Icon(_playerPCMF32.isPlaying
? Icons.stop
: Icons.play_arrow),
onPressed: () {
_playerPCMF32.isPlaying ? _pausePCMF32() : _playPCMF32();
},
),
Text('测试32位浮点数(PCMF32)'),
],
),
),
],
),
),
);
}
}
更多关于Flutter音频播放插件raw_sound的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频播放插件raw_sound的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,raw_sound
是一个用于播放音频的插件,特别适用于播放RAW格式的音频数据。它允许你直接从内存或文件中播放原始的PCM音频数据。以下是如何使用 raw_sound
插件在Flutter项目中播放音频的步骤。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 raw_sound
插件的依赖。
dependencies:
flutter:
sdk: flutter
raw_sound: ^0.2.0 # 请确保使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入 raw_sound
插件。
import 'package:raw_sound/raw_sound.dart';
3. 初始化 RawPlayer
RawPlayer
是 raw_sound
插件中的核心类,用于管理和控制音频播放。
RawPlayer _rawPlayer = RawPlayer();
4. 配置音频数据
raw_sound
插件允许你从文件中加载音频数据或直接提供PCM数据。
从文件中加载音频数据
void _loadAudioFromFile() async {
ByteData audioData = await rootBundle.load('assets/audio/sample.raw');
Uint8List audioBytes = audioData.buffer.asUint8List();
_rawPlayer.load(audioBytes);
}
直接提供PCM数据
void _loadAudioFromPCM(Uint8List pcmData) {
_rawPlayer.load(pcmData);
}
5. 控制播放
你可以使用 RawPlayer
的以下方法来控制音频的播放、暂停和停止。
void _playAudio() {
_rawPlayer.play();
}
void _pauseAudio() {
_rawPlayer.pause();
}
void _stopAudio() {
_rawPlayer.stop();
}
6. 释放资源
在不再需要 RawPlayer
时,记得释放资源以避免内存泄漏。
void _disposePlayer() {
_rawPlayer.dispose();
}
7. 完整示例
以下是一个完整的示例,展示了如何使用 raw_sound
插件播放音频。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:raw_sound/raw_sound.dart';
class AudioPlayerScreen extends StatefulWidget {
[@override](/user/override)
_AudioPlayerScreenState createState() => _AudioPlayerScreenState();
}
class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
RawPlayer _rawPlayer = RawPlayer();
[@override](/user/override)
void initState() {
super.initState();
_loadAudioFromFile();
}
void _loadAudioFromFile() async {
ByteData audioData = await rootBundle.load('assets/audio/sample.raw');
Uint8List audioBytes = audioData.buffer.asUint8List();
_rawPlayer.load(audioBytes);
}
void _playAudio() {
_rawPlayer.play();
}
void _pauseAudio() {
_rawPlayer.pause();
}
void _stopAudio() {
_rawPlayer.stop();
}
[@override](/user/override)
void dispose() {
_rawPlayer.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Raw Sound Player'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _playAudio,
child: Text('Play'),
),
ElevatedButton(
onPressed: _pauseAudio,
child: Text('Pause'),
),
ElevatedButton(
onPressed: _stopAudio,
child: Text('Stop'),
),
],
),
),
);
}
}
void main() => runApp(MaterialApp(
home: AudioPlayerScreen(),
));