【发布时间】:2022-07-16 04:23:27
【问题描述】:
MIDI 通道管理声音、声像、音量等参数;因此,对于合奏音乐,它的每一个真实乐器都应该由它自己的通道来表示。如果涉及超过 15 种非打击乐器,单条 MIDI 线是不够的。
我编写的 Java 软件是为大多数将使用 Java 内置软件合成器的用户设计的。我想允许超过 16 种乐器。据我所知,鉴于现有的 API,我需要几个独立工作的 MidiReceiver 对象。
第一次尝试:软合成器断言“getMaxReceivers() == -1”,即无限,所以我创建了我需要的任意数量。不幸的是,它们都使用相同的渠道——失败。
第二次尝试:我为同一个 Info 对象创建了两个 MidiDevice 对象,并为每个对象创建了一个 MidiReceiver。当我尝试打开第二个时,我收到一个异常,提示没有其他音频线可用。
第三次尝试:与第二次相同,但为了打开设备,我使用 SoftSynthesizer 类的特殊方法,允许我使用给定的音频线打开它;我这样做是使用同一行。没有抛出异常——但音频输出混乱。由于这两个对象彼此不了解,因此它们无法优雅地添加它们的输出。又失败了。
问题:
A) 我是否忽略了什么?
B) 如果没有,有联系人和声誉的人会提醒 Java 接口和 SoftSynthesizer 的作者吗?我的建议,微创:(Soft)Synthesizer 对象应该被赋予额外的方法,例如“MidiDevice getSubdevice()”,getReceiver() 在该方法上根据需要提供新的通道。
(重新编辑后:难道普通的 getReceiver() 方法实际上就是为此目的,如我上面的“第一次尝试”中所述,并且只是被 SoftSynthesizer“Gervill”错误实现了吗?如果是这样, Gervill 应该被告知,但是通过谷歌搜索并不容易找到。您可能知道如何联系他/她/他们。)
public boolean GetTwoIndependenttReceivers (Receiver [] inhereplease)
{
for (MidiDevice.Info info : MidiSystem.getMidiDeviceInfo ()) try
{
MidiDevice device = MidiSystem.getMidiDevice (info);
if ( device instanceof Synthesizer
&& ( device.getMaxReceivers () < 0
|| device.getMaxReceivers () >= 2)) try
{
device.open ();
inhereplease [0] = device.getReceiver ();
inhereplease [1] = device.getReceiver ();
// will be distinct as objects, but with Gervill not independent
return true;
} catch (Exception ex) {}
} catch (Exception ex) {}
return false;
}
请注意,例如,免费软件 MuseScore 使用自己的软件合成器可以很好地解决问题。它导出带有“MIDI 端口”MIDI 消息的 MIDI 文件,正如 MIDI 标准为此目的所设计的那样,并优雅地导入它们。内置的 Java 定序器会简单地忽略这些端口消息,因此会错误地播放文件。这可能是解决问题的额外动机:每个端口都有一个 Receiver 对象。
【问题讨论】:
-
欢迎来到 Stack Overflow。 “如果没有,有联系和声誉的人会不会提醒作者?”作者什么?软件合成器?还是 MIDI 规范? “那岂不是很丢脸,应该马上修改?”请阅读stackoverflow.com/help/dont-ask。 “内置 Java 定序器” 如果您专门编写 Java 代码并试图获得帮助,请出示 minimal reproducible example 并使用 Java 标记来回答您的问题。另外,请阅读How to Ask 并注意这不是论坛。
-
只是一个想法:为什么不使用 OSC 协议呢?
-
谢谢,Karl Knechtel;我尽力重新编辑我的问题。无需修改 MIDI 规范,因为它们已经解决了问题(对于标准 MIDI 文件)。目前我没有看到我可以添加什么代码,因为毫无疑问我的尝试迄今为止失败的原因。
标签: java midi synthesizer gervill audio-channels