在线作曲(唱歌)插件
-
MidiProduce
在线作曲插件
安装方法
下载见
release
- 打开
plugins
文件夹 - 丢进去
- 关闭文件夹
效果
狂乱木曜日 · 爱你
>g;bE;sing;2x>f-[如]~[果]~[你]~[突然] f[打了]~[个] | d.[喷]f-[嚏] o | c-[那]~[一]~[定]~[就是] g[我]e[在] | f.[想]c-[你]&c+ | f-[如]~[果]~[星]~[期四] a[被手]f[机] | f.[吵]d.[醒]d[啊] | c-[那]~[是]~[想]~[吃] g[肯]e[德] | f+[基] a↓[常]b↓[常] | c+[想] f[起] f-[肯] e.[德] d[基]d[的] d-[黄] c+[金] g[硬]↓b[脆]↓ | a[皮].↓ a[鸡]↓-&a | f↓[明]f↓[明] d[很] e[想]-d.[吃] c+[鸡] a↓[却] | b↓[又]c [忍]d[不] e[住]-d.[怀] c+[疑] o- | c+[在] f[你]f-[的]e.[心] d+[里] d[我] | c[是]g[否] g[就] e-[是]f.[唯] a+[一] b+[爱] a[就]g[是]f[请] | f[我]d[吃] e[肯]-f.[德] g++[基]
使用方法
普通指令(轨道语法):
>params>sequence
在 mider code 中,
>params>sequence
可以称作一条轨道params
参数之间用
;
号分隔
支持的参数params
详细说明如下:g|f|数字+b
设置 bpm 同时确定音域, f 表示低音 (pitch=3&bpm=80), g 表示高音 (pitch=4&bpm=80) 必选参数不可省略. 示例:
>g> >f> >120b>
[数字+x]
设置倍速, 支持整数和小数[/+数字]
以设定值为音符默认时值[数字+%]
设置轨道音量[数字+dB]
以设定值为音符默认音量, 范围 0~127[调号]
默认当前音符序列为 C大调 并将其转调到指定调号. 调号由两部分组成: 一部分是调的名字, 具体参考乐理, 需要大写, 另一部分是调的模式, major 和 minor 分别可以简写成 maj 和 min. 若为 minor 则为同名小调. 在一般情况下 major 可以省略. 示例:
>g;Cmin> >g;#Fmajor> >g;bD>
[数字]
设置默认音高[数字/数字]
设置拍号[i=instrument]
设置乐器,instrument
见 MidiInstrument.kt[midi|img|pdf|mscz]
上传乐谱文件, 如是 img 则会上传图片 注: 涉及乐谱生成需要先安装 Muse Score 见 转换乐谱[sing:area:singerId]
调用 sinsy 接口生成音频. 当 area 和 singerId 都提供时, singerId的格式为 [f|m]+数字 表示选取的是该地区的 第 singerId 位 女性|男性 歌手. 当仅提供 singerId 时, 其格式为 数字, 表示选取 表示符 为 singerId 的歌手. 当两者都不提供时, 相当于选取中国大陆地区的第一位女歌手 香玲
sequence
sequence 可以是音名序列或是唱名序列, 音名序列的判断标准是序列里是否出现了
c~a
或C~B
中任何一个字符音符
音名序列下, 使用 cdefgabCDEFGAB 表示, 其中小写写表示 pitch=4的音符, 大写表示比小写高一个八度的音符
唱名序列下, 使用 1234567 表示
创建的音符默认时值是四分音符, 要修改其时值, 可以使用
+
来拉长音符时值,-
以缩短时值
例如以下示例就创建了一个八分音符, 十六分音符和一个二分音符>g>c- #八分音符 >g>c-- #十六分音符 >g>c+ #二分音符
要为音符添加附点, 请在该音符后加上
.
, 而特殊时值例如三连音可以使用/
>g>a. c/3 c/3 c/3
#
和$
分别可以让音符升高或降低半音,@
表示给音符添加一个还原符号>g>$e @f #c
&
可以将多个音符的时值连在一起组成一个音符>g>a&a- # 等价于以下 >g>a.
而在唱名序列中,
$
可以用b
代替>g>12b3
在音符后加上数字可以改变其八度
>g>c3 e5
而更推荐的做法是使用
↑
和↓
在 pitch=4 的基础上进行八度的增减. 而在唱名序列中,↑
和↓
可以用i
和!
代替>g>c↓ e↑ g↑↑ >g>1↓ 3↑ 5↑↑ >g>1! 3i 5ii
%
可以设置单个音符的力度, 范围是 0~127, 未设置的情况下默认力度为 100>g>c%60
使用
o
或O
创建四分休止符或二分休止符, 休止符同样可以使用+
,-
.
甚至/
来修改时值. 在 唱名序列中0
相当于 四分休止符>g>o-O+O.
[
配合]
可以给单个音符加上歌词>g>1[打]2[倒]3[列]1[强]
要重复单个音符多次可以使用
*
>g>c*100
~
可以克隆前一个音符,适合偷懒>g>c~~~~~~
^
和v
可以将上一个音符克隆并升高或降低一个音, 升高或降低的音满足在 C大调 下的音程关系. 类似的用法还有m-w
,n-u
,q-p
,i-!
,s-z
升高或降低度数在 ^-v 的基础上逐步递增或递减>g>c^^^ # 等价于 cdef
和弦
使用
:
可以将多个音符组成一个和弦, 第一个音的时值将会是和弦的时值>g>c:e:g
^
和v
等 也是可用的>g>c:m:m # 等价于 c:e:g
但是 使用
^
和v
等 时要注意,#
和$(b)
将不起作用>g>c:m:#m #号 将不起作用
可以使用
"
和'
代替#
和$(b)
问就是起名废>g>c:m:m'
↟
和↡
可以创建向上或向下琶音符号越来越奇怪了啊喂>g>c:e:g↟
倚音
;
连接两个音符组成一个短前倚音, 倚音时值为第二个音符的时值>g>c;e
若要构建后倚音只需要在第二个音符后加上
t
>g>c;et
滑音/刮奏(Glissando)
使用
=
, 可以连接多个音符, 时值为所有组成音符的时值. 默认只刮白键>g>c=b
若要白键和黑键一起刮, 在后面加上
t
>g>c=bt
宏
mider code 中宏的本质是对某段序列或其中的字母或数字的重复或简单修改替换.
碍于技术原因, 目前宏均不可嵌套使用
宏的定义始于
(
终于)
,()
内便是宏的作用域, 以下是支持的宏:定义一个音符序列:
(def symbol=note sequence)
>g>aaa(def na=cde)aaa >g>aaaaaa # 实际输入的序列
定义一个音符序列, 并在此处展开:
(def symbol:note sequence)
>g>aaa(def na=cde)aaa >g>aaacdeaaa # 实际输入的序列
展开 symbol 对应音符序列:
(=symbol)
>g>(def a=cde)a(=a) >g>acde # 实际输入的序列
读取 path 代表的资源并展开, 如果是文件默认目录是插件的数据文件夹:
(include path)
>g>(include ./seq.midercode)
将音符序列重复 times 次:
(repeat time: note sequence)
>g>c(repeat 3: oa) >g>coaoaoa # 实际输入的序列
如果定义了 symbol 则展开:
(ifdef symbol: note sequence)
如果未定义 symbol 则展开:
(if!def symbol: note sequence)
>g>(def s=abc) (ifdef s: cfg) (if!def s: bbc) >g>cfg #实际输入的序列
定义宏(类似函数, 但实际表现得更蠢一些):
(macro name param1[,params]: note sequence @[param1])
展开宏: (!name arg1[,arg2])
>g>(m p1: a@[p1]dc@[p1]) (!m b) >g>abdcb #实际输入的序列
调整 note sequence 的力度, 仅适用于长音名序列:
(velocity linear from~to: note sequence)
>g>(velocity linear 50~80: cde) >g>c%50 d%60 e%70
环境指令:
>!config>
供 MidiProduce 内部调用
获取帮助>!help>
设置 formatMode
>!formatMode=mode>
清理缓存
>!clear-cache>
todo list
- 解析音符为语音
- 渲染乐谱
- 识别乐谱并转化为音符
示例
1. 小星星 >g>1155665 4433221 5544332 5544332 等同于 >g>ccggaag+ffeeddc+ggffeed+ggffeed 等同于 >g>c~g~^~v+f~v~v~v+(repeat 2:g~v~v~v+) (酌情使用 2. KFC 可达鸭 >g;bE>g^m+C-wmD+D^m+G-wmE+D^w+C-wmD+DvagaC 3. 碎月 >85b>F+^$BC6GFG C$E F D$ED$b C+ g$b C$E F$E F+ F$E F$B G++ G$B C6C6$B C6 G+ G$E FGF$E C+ C$b C+C$EF$EFG $E 等同于 >85b;Cmin>F+^BC6GFG CE F DEDb C+ gb CE FE F+ FE FB G++ GB C6C6B C6 G+ GE FGFE C+ Cb C+CEFEFG E 4. 生日快乐 >88b>d.d- e+v g+ #f++ d.d- e+v a+ v+ d.d- D+b+g+ #f+ e+ C.C- b+ g+^ v+ 5. 茉莉花 >110b>e+em^m~wv+g^v++e+em^m~wv+g^v++g+~~em^+av~++e+d^m+evv+c^v++evvmv+.eg+amg++d+egd^cwv++ ^-c+d+.ec^vwv++ 6. bad apple! >100b>e#fgab+ ED b+ e+ b a-- B-- A- g#f e#fga b+ ag #fe#fg #f--G--#F-e #d#f e#fgab+ ED b+e+ ba--B--A- g#f e#fgab+ ag 7. Jingle Bells >100b>E~~+E~~+EmC^^++F~~+Fv~+Ev~^ D+G+E~~+E~~+EmC^^++F~~+Fv~~m~vDv++ 8. 两只老虎 卡农 >g;3>(def tiger:1231 1231 3450 3450 5-6-5-4-31 5-6-5-4-31 15!10 15!10) >g;4>00(=tiger) >g;5>0000(=tiger) >g;6>000000(=tiger) >g;7>00000000(=tiger)
更多示例见 awesome-melody
若想分享自己编写的旋律欢迎提
pr
到这个文件夹, 建议使用英文名称, 后续可能会考虑打包进发布版本供include
使用转换乐谱
此功能需要首先安装 Muse Score
下载
Muse Score
: 可以根据官方 下载页面 也可以参考 snapcraft附官方
linux
安装指北安装完成后将
Muse Score
的运行目录 (包括bin/
) 添加到环境变量或者也可以修改配置中
mscoreConvertMidi2MSCZCommand
等的值为安装目录如您的安装的可执行程序启动命令(可执行程序的名字)不是
MuseScore3
, 您需要手动将config.yml
中的MuseScore3
替换成正确的MuseScore
启动命令最后在轨道中添加
;pdf
或;img
即可得到渲染好的乐谱若想修改
Muse Score
命令格式和参数, 请参考 官方使用手册注意
- 唱名序列中
\s{2}
和\s\|\s
会被自动替换成0
也就是休止符, 可以在配置中修改这部分行为 - 若为使用
internal
模式则生成的语音音色会随着系统底层实现的不同而不同 - 如果最后输出的格式是
silk
那么好友和群聊都有效, 如果是mp3
则仅群聊有效, 好友会出现感叹号 mp3
格式在pc
端听不了,mac
据说可以, 哪位富婆可以给咱买一台测试一下(- 命令还未加入权限, 可以在 #3 进行讨论
- 好友环境下生成
silk
格式会比mp3
音质低得多, 听个响属于是
构建
由于使用了 RainChan 的 silk4j 所以
clone
到本地后要修改build.gradle.kts
中的username
和password
为自己的才能成功构建服务器环境下生成语音
在服务器环境插件可能会由于缺少硬件或驱动支持无法生成语音, 可以尝试安装 timidity 和 ffmpeg 解决
具体安装可以参考 这篇
这里提供一个
sf2
的 音色库安装完成以后确保
timidity
和ffmpeg
位于环境变量中, 或者也可以修改ffmpegConvertCommand
和timidityConvertCommand
最后修改
formatMode
即可使用timidity
和ffmpeg
生成语音修改音色
目前
internal
无法修改音色可以通过安装
timidity
或Muse Score
来实现release 中的多个发行包
带
bundled-silkf4
的是打包了 silk4j 的包若确定不需要使用转换
silk
的功能可以直接下载不带后缀版本的包 - 打开
-
是midi吗()
-
@藤原白叶 是的
-
那降号怎么打?
-
@lyjdht 降号是$和#一样打在音名前面
-
那音符长度呢。。
-
@lyjdht 默认情况下,单独一个音名是四分音符,可以在后面加-或+来缩短或者拉长时值 比如 a是四分音符长度,a-是八分音符,a+是二分音符,+和-可以累加,附点在音名后面加.即可
-
来自mavenLocal的那些jar,不妨也加到项目文件里供其他开发者获取?我想试试运行源码
-
@hundun000 所用的两个库已上传到
jitpack.io
clone插件最新版本就可以构建成功, 或者在原有工程的dependencies
加入如下依赖implementation 'com.github.nwaldispuehl:java-lame:v3.98.4' implementation 'com.github.whiterasbk:mider:kbeta0.9.1'
-
@whiterasbk ok
-
![RIYI9E)ACRN42D~FRWIT5N.png
![EGCGZ8R~TTPW$B]V5WG$8O.png请问一下这是为什么 -
使用指令报错了
E/MidiProduce: Exception in coroutine Plugin bot.music.whiter.MidiProduce of MidiProduce java.lang.NoClassDefFoundError: Could not initialize class whiter.music.mider.dsl.FuncKt at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.UtilsKt.midi2mp3Stream(utils.kt:49) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.UtilsKt.midi2mp3Stream$default(utils.kt:47) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$generate$2.invokeSuspend(MidiProduce.kt:71) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$generate$2.invoke(MidiProduce.kt) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$generate$2.invoke(MidiProduce.kt) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.UtilsKt.matchRegex(utils.kt:16) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.UtilsKt.matchRegex(utils.kt:20) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce.generate(MidiProduce.kt:45) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce.access$generate(MidiProduce.kt:14) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$onEnable$2.invokeSuspend(MidiProduce.kt:29) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$onEnable$2.invoke(MidiProduce.kt) at MidiProduce-0.1.3.mirai.jar//bot.music.whiter.MidiProduce$onEnable$2.invoke(MidiProduce.kt) at net.mamoe.mirai.event.EventChannel$subscribeAlways$1.invokeSuspend(EventChannel.kt:455) at net.mamoe.mirai.event.EventChannel$subscribeAlways$1.invoke(EventChannel.kt) at net.mamoe.mirai.event.EventChannel$subscribeAlways$1.invoke(EventChannel.kt) at net.mamoe.mirai.internal.event.Handler$onEvent$2.invokeSuspend(InternalEventListeners.kt:50) at net.mamoe.mirai.internal.event.Handler$onEvent$2.invoke(InternalEventListeners.kt) at net.mamoe.mirai.internal.event.Handler$onEvent$2.invoke(InternalEventListeners.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89) at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:166) at kotlinx.coroutines.BuildersKt.withContext(Unknown Source) at net.mamoe.mirai.internal.event.Handler.onEvent(InternalEventListeners.kt:50) at net.mamoe.mirai.internal.event.InternalEventListenersKt.process(InternalEventListeners.kt:166) at net.mamoe.mirai.internal.event.InternalEventListenersKt.callAndRemoveIfRequired(InternalEventListeners.kt:115) at net.mamoe.mirai.internal.event.InternalEventListenersKt$callAndRemoveIfRequired$1.invokeSuspend(InternalEventListeners.kt) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.UndispatchedCoroutine.afterResume(CoroutineContext.kt:202) at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:102) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
-
我也遇到报错了,源头应该是在错误日志更下面的部分,看起来是因为服务器环境运行却试图用某些desktop工具?
0|mcl | java.lang.ExceptionInInitializerError 0|mcl | at bot.music.whiter.UtilsKt.midi2mp3Stream(utils.kt:49) 0|mcl | at bot.music.whiter.UtilsKt.midi2mp3Stream$default(utils.kt:47) 0|mcl | at bot.music.whiter.MidiProduce$generate$2.invokeSuspend(MidiProduce.kt:71) 0|mcl | at bot.music.whiter.MidiProduce$generate$2.invoke(MidiProduce.kt) 0|mcl | at bot.music.whiter.MidiProduce$generate$2.invoke(MidiProduce.kt) 0|mcl | at bot.music.whiter.UtilsKt.matchRegex(utils.kt:16) 0|mcl | at bot.music.whiter.UtilsKt.matchRegex(utils.kt:20) …… 0|mcl | Caused by: javax.sound.midi.MidiUnavailableException: Can not open line 0|mcl | at java.desktop/com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1180) 0|mcl | at java.desktop/com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1090) 0|mcl | at java.desktop/com.sun.media.sound.SoftSynthesizer.getReceiverReferenceCounting(SoftSynthesizer.java:1395) 0|mcl | at java.desktop/javax.sound.midi.MidiSystem.getReceiver(MidiSystem.java:237) 0|mcl | at java.desktop/javax.sound.midi.MidiSystem.getSequencer(MidiSystem.java:416) 0|mcl | at java.desktop/javax.sound.midi.MidiSystem.getSequencer(MidiSystem.java:339) 0|mcl | at whiter.music.mider.dsl.FuncKt.<clinit>(func.kt:12) 0|mcl | ... 73 more 0|mcl | Caused by: java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian is supported. 0|mcl | at java.desktop/javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:425) 0|mcl | at java.desktop/javax.sound.sampled.AudioSystem.getSourceDataLine(AudioSystem.java:534) 0|mcl | at java.desktop/com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1120) 0|mcl | ... 79 more
-
我也报错了,运行不起来
-
???阁下还兼音乐这块的技术
-
@zyyan 请提供运行环境(包括系统等)信息和mirai版本号
-
@CCYellowStar 请提供运行环境(包括系统等)信息和mirai版本号
-
@hundun000 请提供运行环境(包括系统等)信息和mirai版本号和尝试执行的音符序列
-
@whiterasbk mirai是2.11.0版本,运行环境Windows Server2012,尝试你列出来的小星星预设
-
@whiterasbk
音符序列是小星星样例0|mcl | 2022-05-27 16:11:56 I/main: Backend: version 2.10.0, built on 2022-02-01 00:02:35. 0|mcl | 2022-05-27 16:11:56 I/main: Frontend Terminal: version 2.10.0, provided by Mamoe Technologies openjdk version "11.0.13" 2021-10-19 OpenJDK Runtime Environment (build 11.0.13+8-Ubuntu-0ubuntu1.20.04) OpenJDK 64-Bit Server VM (build 11.0.13+8-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)