在 Java 中同时播放 .mp3 和一系列音符 (MIDI)
Play .mp3 and a sequence of notes (MIDI) simultaneously in Java
我目前正在开发一个应用程序,用户可以在其中加载 .mp3 文件并输入一系列音符。用户的目标是将这个音符序列与 .mp3 文件的歌曲相匹配。
这需要能够同时播放 .mp3 文件和音符序列。经过一些研究,我发现 Java Sound API or JFuge can do the job to produce a sequence of notes (MIDI). (The input given by the user). As stated here,JLayer 可以用来播放 Java 中的 mp3 文件。 (我也可以将 .mp3 转换为 .wav 并使用另一种方式播放转换后的 .wav)。
但是,是否可以一起播放此 .mp3 和一系列音符而不会出现任何问题,还是我应该先将它们转换为一个文件?
用户应该能够同时播放任意随机时间戳的 .mp3 和 his/her 音符序列。最好没有任何延迟,以便用户可以轻松调整音符以匹配文件的音调。似乎将它们合并到一个文件中,然后再播放它们,当用户几乎不断地更改音符并重播以检查它是否与音高匹配时,开销会太大。
提前致谢!
Java 支持多线程播放。您需要做的就是 运行 来自一个线程的 .mp3,以及同时 运行ning 线程上的另一个 midi 生成的音符。
曾经有几个 Linux 系统一次只能处理一个音频源的输出。我不知道这是否仍然是一个问题。
另一种更复杂的可能性可以让您进行现场混音并输出到单行是使用 AudioInputStream 读取歌曲文件,即时将字节转换为 PCM(例如,从 - 1 到 1)(或预加载音频并将其存储为 PCM),然后将其添加到来自自己动手合成器的 PCM 数据中,然后将其转换回字节并通过 SourceDataLine 输出。
这很麻烦,您可能不想走那条路,但如果您这样做了,以下是一些信息,可帮助分解一个可能实现的各个步骤。
Loading .wav data and converting it into an internal PCM form can be seen in the open-source AudioCue (line 359 loadURL
method). And here 是我制作的实时 Java 合成器的示例(免费下载) 运行s 通过击键。其中一个声音是一个简单的风琴,它通过仅在谐波频率上添加四个正弦波来输出 PCM 音频数据。如果您想进入其他形式的合成但参与得更多,则可以制作其他声音。
(IDK 如何转换来自 MIDI 控制的合成器的数据,除非可以识别 TargetDataLine,并且来自它的数据转换为 PCM 类似于在 AudioCue 源示例中从 AudioInputStream 读取时使用的转换。 )
给定两个 PCM 源,可以使用加法将两者实时混合,转换为字节并通过单个 SourceDataLine 输出(参见第 1387 行 convertBufferToAudioBytes
方法)。如果您在贡献者不玩时输入零,则 SourceDataLine 可以无限期地保持 运行ning。 SDL 绝大部分时间都处于阻塞状态,因为音频数据处理比系统消耗它的速率快得多,因此使用很少 cpu.
我目前正在开发一个应用程序,用户可以在其中加载 .mp3 文件并输入一系列音符。用户的目标是将这个音符序列与 .mp3 文件的歌曲相匹配。
这需要能够同时播放 .mp3 文件和音符序列。经过一些研究,我发现 Java Sound API or JFuge can do the job to produce a sequence of notes (MIDI). (The input given by the user). As stated here,JLayer 可以用来播放 Java 中的 mp3 文件。 (我也可以将 .mp3 转换为 .wav 并使用另一种方式播放转换后的 .wav)。
但是,是否可以一起播放此 .mp3 和一系列音符而不会出现任何问题,还是我应该先将它们转换为一个文件?
用户应该能够同时播放任意随机时间戳的 .mp3 和 his/her 音符序列。最好没有任何延迟,以便用户可以轻松调整音符以匹配文件的音调。似乎将它们合并到一个文件中,然后再播放它们,当用户几乎不断地更改音符并重播以检查它是否与音高匹配时,开销会太大。
提前致谢!
Java 支持多线程播放。您需要做的就是 运行 来自一个线程的 .mp3,以及同时 运行ning 线程上的另一个 midi 生成的音符。
曾经有几个 Linux 系统一次只能处理一个音频源的输出。我不知道这是否仍然是一个问题。
另一种更复杂的可能性可以让您进行现场混音并输出到单行是使用 AudioInputStream 读取歌曲文件,即时将字节转换为 PCM(例如,从 - 1 到 1)(或预加载音频并将其存储为 PCM),然后将其添加到来自自己动手合成器的 PCM 数据中,然后将其转换回字节并通过 SourceDataLine 输出。
这很麻烦,您可能不想走那条路,但如果您这样做了,以下是一些信息,可帮助分解一个可能实现的各个步骤。
Loading .wav data and converting it into an internal PCM form can be seen in the open-source AudioCue (line 359 loadURL
method). And here 是我制作的实时 Java 合成器的示例(免费下载) 运行s 通过击键。其中一个声音是一个简单的风琴,它通过仅在谐波频率上添加四个正弦波来输出 PCM 音频数据。如果您想进入其他形式的合成但参与得更多,则可以制作其他声音。
(IDK 如何转换来自 MIDI 控制的合成器的数据,除非可以识别 TargetDataLine,并且来自它的数据转换为 PCM 类似于在 AudioCue 源示例中从 AudioInputStream 读取时使用的转换。 )
给定两个 PCM 源,可以使用加法将两者实时混合,转换为字节并通过单个 SourceDataLine 输出(参见第 1387 行 convertBufferToAudioBytes
方法)。如果您在贡献者不玩时输入零,则 SourceDataLine 可以无限期地保持 运行ning。 SDL 绝大部分时间都处于阻塞状态,因为音频数据处理比系统消耗它的速率快得多,因此使用很少 cpu.