Flutter音频处理插件csounddart的使用
Flutter音频处理插件csounddart的使用
csounddart
是一个 Dart 接口,用于与 Csound API 进行交互。该项目旨在为使用 Flutter 和 Csound 创建应用程序提供统一的 API,无论目标平台是什么(如 Linux、MacOS、Windows、Web、Android、iOS 等)。
目前该项目仍在开发中。已在 Linux、MacOS、Windows 和 Android 上进行了测试。当前 Web 版本尚未正常工作。
在桌面平台上,它假定 Csound 已安装在您的计算机上。在 Android 平台上,它会下载并安装 Csound 库到应用包中。
开始使用
import 'package:csounddart/csound.dart';
// 创建 Csound 对象在一个新的 Isolate 中(类似于 Dart 线程)。
// 由于当前实现,所有与 Csound 的事务都通过向隔离区发送消息来异步执行。
Csound _cs = Csound();
// 编译 Csound CSD 文本并获取返回值
int res = await _cs.compileCsdText(_myCsdText);
// 读取一段乐谱
int res = await _cs.readScore(_myScore);
// 从路径编译
int res = await _cs.compileCsd(_myCsd);
// 编译 Orchestra
int res = await _cs.compileOrc(_orchestra);
// 多线程表演
_cs.perform();
// 暂停或重新开始表演
_cs.pause(bool);
// 设置通道值
_cs.setControlChannel("channelName", (double)value);
// 设置回调。传递的方法将在每次 k-pass 时被调用。
_cs.setControlChannelCallback("channelName",
(double v) {
// 在这里进行回调操作
}
);
// 音频回调
_cs.setAudioChannelCallback("audioChannelName",
(ConcurrentBuffer buf) {
for(int i = 0; i < buf.length; i++) {
double value = buf.get(i);
}
}
);
// 获取控制通道值
double channel = _cs.getControlChannel("channemName");
// 获取 Csound 值
int ksmps = await _cs.getKsmps();
int nchnls = await _cs.getNchnls();
int sr = await _cs.getSr();
int dbfs = await _cs.get0dbfs();
// 停止 Csound,清除所有回调内存。
_cs.stop();
// 如果正在表演,则停止表演,并销毁 Csound 实例,所有回调内存和杀死隔离区。
// 重新开始表演涉及通过调用构造函数 `Csound()` 重新创建对象。
_cs.destroy();
// 重置 Csound
_cs.reset();
待办事项
- Android : 音频通道回调似乎已损坏。
- 统一 ConcurrentBuffer 以便用户可以更方便地使用。
完整示例代码
示例代码
import 'dart:io';
import 'package:csounddart/csound.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:csounddart/csounddart.dart';
import 'package:oscilloscope/oscilloscope.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
void requestPermission() async {
if (Platform.isAndroid) {
Map<Permission, PermissionStatus> lst = await [Permission.storage,
Permission.microphone, Permission.sensors].request();
}
}
[@override](/user/override)
void initState() {
super.initState();
initPlatformState();
requestPermission();
}
late Csound _cs;
static const String _csd = """
<CsoundSynthesizer>
<CsOptions>
-odac
;-iadc
;-B 1024
;-b 256
</CsOptions>
; ==============================================
<CsInstruments>
sr = 44100
ksmps = 32
nchnls = 2
nchnls_i = 1
0dbfs = 1
opcode mtofi,i,i
imid xin
iout = 440 * exp(0.0577622645 * (imid - 69))
xout iout
endop
instr 1
inote init p4
ivel init p5
ifq = mtofi(inote)
kfq = k(ifq)
iT = 1000 / ifq
aPulse = linseg:a(1, iT/1000, 0)
aPulse = (aPulse + (noise:a(1,0.5) * aPulse)) / 2
aPulse = aPulse * pow(2, ((1-((ivel-1)/126)) * -4 ))
iff = ivel * 100 + 20
aPulse = butterlp(aPulse, iff)
;resonr allows to clear internal space
alow, ahigh, ao svfilter aPulse, kfq, 500
//ao = butterbp(aPulse, kfq, 1500)
amo = ao * 15
amo -= 3.25
amo = butterlp(amo, 150)
//ao = lowpass2:a(amo, 150, 50)
amo = distort1( amo, 1, 1, 0, 0)
; Two parallel lines
;one raising, removing gain, and DC
a1 = (pow(amo, 2)) * (-0.08)
a1 = dcblock(a1)
a2 = butterhp(amo, 250) * 0.25
as = limit( ((a1 * 0.0001) + a2 + ao) * 0.7 , -1, 1)
as = dcblock(as)
outs as, as
endin
instr 2
ao = oscili(0.3, linseg:k(100, p3, 400))
av = vco2(0.3, linseg:k(1, p3, 10))
chnset(av, "vco")
ao4 = oscili(1.0, linseg:k(1000, p3, 10))
chnset(ao4, "sine")
outs ao,ao
endin
instr 3
;kfq init 200
kfq = chnget:k("freq")
printk 1, kfq
ao = vco2(0.15, kfq) * 0.1
chnset(ao, "audioChannel")
ko = k(ao)
chnset(ko, "controlChannel")
;ain = inch(1)
;aVoice = ain * 0.3
;aVoice = delay(ain, 1) * 0.2
,aVoice = comb(aVoice, 3.5, 0.1) * 0.1 + (ain * 0.3)
; outs aVoice, aVoice
outs ao,ao
endin
instr 4
ao = oscili(0.15, 400)
outs ao,ao
endin
</CsInstruments>
; ==============================================
<CsScore>
i 3 0 100
</CsScore>
</CsoundSynthesizer>
""";
// 平台消息是异步的,因此我们初始化在一个异步方法中。
Future<void> initPlatformState() async {
print("Init Platform State");
String platformVersion;
// 平台消息可能会失败,所以我们使用 try/catch PlatformException。
// 我们还处理消息可能返回 null 的情况。
try {
platformVersion =
await Csounddart.platformVersion ?? 'Unknown platform version';
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// 如果在异步平台消息还在飞行时小部件从树中移除,我们希望丢弃回复而不是调用
// setState 来更新我们的不存在的外观。
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
double _sliderFreq = 200;
List<double> _dataSet = [];
bool _pause = false;
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Csound Dart 示例'),
),
body: Center(
child: Container(
child: SingleChildScrollView(
child: Column(
children: [
Text('运行在: $_platformVersion\n'),
Container(
height: 3,
),
ElevatedButton(
onPressed: () async {
_cs.reset();
},
child: Text("重置")),
Container(
height: 3,
),
ElevatedButton(
onPressed: () async {
_cs = Csound(onReady: () {
print("Csound Compile");
// print(_csd);
int res = _cs.compileCsdTextSync(_csd);
print("compile res $res");
// int ksmps = await _cs.getKsmps();
// print("ksmps = $ksmps");
if (res != 0) return;
_cs.perform();
_cs.setControlChannel("freq", 200.0);
/*
_cs.setControlChannelCallback("controlChannel", (double val) {
if (_dataSet.length > 1024) _dataSet.clear();
_dataSet.add(val);
});
*/
/*
_cs.setAudioChannelCallback("audioChannel", (data) async {
if (_dataSet.length > 1024) _dataSet.clear();
for (int i = 0; i < data.length; i++) {
_dataSet.add(data.get(i));
}
});
*/
},
onStop: () {
print("csound stopped callback");
}
);
},
child: Text("播放")),
Container(
height: 3,
),
ElevatedButton(
onPressed: () {
_cs.stop();
print("想要停止");
},
child: Text("停止")),
Container(height: 5),
ElevatedButton(
onPressed: () async {
_cs.destroy(onDestroyed: () {
print("Csound Destroy callback");
});
},
child: Text("销毁")),
Container(height: 5),
ElevatedButton(
onPressed: () async {
_pause = !_pause;
_cs.pause(_pause);
},
child: Text("暂停")),
Container(height: 5),
Slider(
onChanged: (double v) {
setState(() {
_sliderFreq = v;
});
_cs.setControlChannel("freq", _sliderFreq);
},
value: _sliderFreq,
min: 100,
max: 500,
),
Container(
width: 400,
height: 150,
child: Oscilloscope(
showYAxis: true,
yAxisColor: Colors.orange,
margin: EdgeInsets.all(20.0),
strokeWidth: 1.0,
backgroundColor: Colors.black,
traceColor: Colors.green,
yAxisMax: 1.0,
yAxisMin: -1.0,
dataSet: _dataSet,
),
)
],
),
),
),
),
),
);
}
}
更多关于Flutter音频处理插件csounddart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter音频处理插件csounddart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
csounddart
是一个用于在 Flutter 中处理音频的插件,它基于 Csound 音频合成系统。Csound 是一个强大的音频合成和处理工具,支持复杂的音频算法和实时音频处理。csounddart
插件允许你在 Flutter 应用中使用 Csound 的功能。
以下是如何在 Flutter 项目中使用 csounddart
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 csounddart
插件的依赖:
dependencies:
flutter:
sdk: flutter
csounddart: ^0.0.1 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 初始化 Csound
在你的 Dart 代码中,首先需要初始化 Csound 实例:
import 'package:csounddart/csounddart.dart';
void main() async {
Csound csound = Csound();
await csound.initialize();
}
3. 编译并运行 Csound 代码
你可以通过 compileOrc
方法编译 Csound 的 .orc
文件或直接传递 Csound 代码字符串。然后使用 readScore
方法加载 .sco
文件或传递 Csound 的乐谱字符串。
void main() async {
Csound csound = Csound();
await csound.initialize();
// 编译 Csound 代码
String orcCode = '''
instr 1
a1 oscil 10000, 440, 1
out a1
endin
''';
await csound.compileOrc(orcCode);
// 加载乐谱
String score = "i1 0 2"; // 在 0 秒开始,持续 2 秒
await csound.readScore(score);
// 开始音频处理
await csound.start();
}
4. 控制音频
你可以通过 csound
实例控制音频的播放、暂停和停止:
// 暂停音频
await csound.pause();
// 恢复音频
await csound.resume();
// 停止音频
await csound.stop();
5. 清理资源
在应用结束时,记得清理 Csound 实例以释放资源:
await csound.cleanup();
6. 处理实时音频输入和输出
csounddart
也支持实时音频输入和输出。你可以通过配置 Csound 的音频设备来实现:
await csound.setOption("-odac"); // 使用默认音频输出设备
await csound.setOption("-iadc"); // 使用默认音频输入设备
7. 处理 MIDI 输入
如果你需要处理 MIDI 输入,可以通过以下方式配置:
await csound.setOption("-M0"); // 使用默认 MIDI 输入设备
8. 处理音频回调
你可以通过 csounddart
提供的回调函数来处理音频数据,例如实时音频处理或音频分析。
csound.setAudioCallback((List<double> buffer) {
// 处理音频数据
});
9. 调试和日志
你可以启用 Csound 的调试日志来帮助调试音频处理代码:
await csound.setOption("-d"); // 启用调试日志