java - 如何在 Java 中以 (MIDI) 序列播放音频剪辑?

标签 java audio midi javasound

我正在尝试用 Java 编写一个非常简单的 DAW,但在播放序列中的音频剪辑时遇到问题。我研究了 Java Sound 中的采样类和 MIDI 类,但我真正需要的是两者的混合。

似乎对于 MIDI 类,您无法使用音序器来播放您自己的音频剪辑。 我尝试使用调度来编写自己的音序器,以按顺序播放 javax.sound.sampled.Clip,但时间变化太大。这实际上并不是一个可行的选择,因为它不节省时间。

有人对我如何解决这个问题有任何建议吗?

最佳答案

我可以证明,可以用 Java 编写结合了 MIDI 和样本方面的音频混合系统,就像我自己编写的一样,它目前可以与我也编写的样本和几个实时合成器一起使用。

关键是使样本的音频数据在每帧的基础上可用,并且帧计数命令处理器/音频混合器既管理“命令”的执行,又收集和混合音频帧数据。在 44100 fps 下,精度约为 0.02 毫秒。如果需要,我可以更详细地描述。

另一种可能更明智的方法是使用Java bridge,尽管我个人没有这样做过。到诸如Jack之类的系统.

<小时/>

编辑:回答评论中的问题(2019 年 12 月 8 日)。

Java 中的音频样本数据通常保存在内存中(Java 使用 Clip)或从 .wav 文件读取。因为 Clip 不会公开各个帧,所以我编写了一个替代方案,并使用它来将数据保存为范围 -1 到 1 的有符号 float 。有符号 float 是保存音频数据的常用方法,我们可以使用它来保存音频数据。将执行多项操作。

对于.wav音频的播放,Java结合使用AudioInputStream读取数据和使用SourceDataLine输出。您的系统必须位于中间,拦截 AudioInputStream,转换为 PCM float 帧,并在运行过程中对帧进行计数。

可以同时处理多个源或轨道,并将其合并(简单添加归一化 float )到单个信号。该信号可以转换回字节并通过单个 SourceDataLine 发送出去进行播放。

从单个 SourceDataLine 中的任意第 0 帧计算输出帧将有助于保持组成的传入轨道协调,并将提供帧编号引用,用于安排您希望之前执行的任何其他命令到正在输出的帧(例如,更改源的音量/声像,或合成器上的设置)。

我个人的剪辑替代方案与 AudioCue 非常相似欢迎您检查和使用。主要区别在于,无论好坏,我在系统中一次一帧地处理所有内容,并且 AudioCue 及其“混合器”处理缓冲区加载。有几个非常可信的人批评我个人的每帧系统效率低下,因此当我为 AudioCue 提供公共(public) API 时,我屈服于这种先入之见。 [有多种方法可以向每帧系统添加缓冲以重新获得效率,并且每帧使调度变得更简单。所以我坚持我的每帧逻辑方案。]

关于java - 如何在 Java 中以 (MIDI) 序列播放音频剪辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59143055/

相关文章:

Java网络驱动程序: How to save the page same as "save page as" in firefox?

kotlin - MediaButtonReceiver.buildMediaButtonPendingIntent() 给出目标 S+(版本 31 及更高版本)需要 FLAG_IMMUTABLE 或

java - 我的应用程序 "find frequency of audio input from microphone"总是崩溃。但为什么?

python - 能否在服务器端使用 Gstreamer 按需将音频流式传输到多个客户端?

ios - Swift UnsafeMutablePointer<Unmanaged<CFString>?> 分配和打印

java - 无法实例化java中的类型

java - Log4j 模式布局 %p token 不起作用

python - 用openai图表txt文件编码到midi转换器

iphone - 使用 Xcode/Cocoa 在 iPhone 中播放 midi 文件或 midi 音色

java - 如何将对象数组从 javascript 传递到 Java