在 Java 中同时播放 .mp3 和一系列音符 (MIDI)
Posted
技术标签:
【中文标题】在 Java 中同时播放 .mp3 和一系列音符 (MIDI)【英文标题】:Play .mp3 and a sequence of notes (MIDI) simultaneously in Java 【发布时间】:2019-08-18 13:08:55 【问题描述】:我目前正在开发一个应用程序,用户可以在其中加载 .mp3 文件并输入一系列笔记。用户的目标是将此音符序列与 .mp3 文件的歌曲相匹配。
这需要能够同时播放 .mp3 文件和音符序列。经过一番研究,我发现Java Sound API 或JFuge 都可以完成产生一系列音符(MIDI)的工作。 (用户给出的输入)。如here 所述,JLayer 可用于播放 Java 中的 mp3 文件。 (我也可以将 .mp3 转换为 .wav 并使用其他方式播放转换后的 .wav)。
但是,是否可以毫无问题地同时播放此 .mp3 和音符序列,还是我应该先将它们转换为一个文件?
用户应该能够在任何随机时间戳同时播放 .mp3 和他/她的音符序列。最好没有任何延迟,以便用户可以轻松地调整音符以匹配文件的音高。当用户几乎不断地更改音符并重放以检查它是否与音高匹配时,在播放它们之前将它们合并到一个文件中似乎会产生太多开销。
提前致谢!
【问题讨论】:
【参考方案1】:Java 支持从多个线程播放。您需要做的就是从一个线程运行 .mp3,然后在另一个并发运行的线程上运行 midi 生成的注释。
曾经有一些 Linux 系统一次只能处理一个音频源的输出。我不知道这是否仍然是一个问题。
另一种更精细的可能性可以让您进行现场混音并输出到单行,即使用 AudioInputStream 读取歌曲文件,即时将字节转换为 PCM(例如,转换为从 -1 到1)(或将音频预加载并存储为 PCM),然后将其添加到来自自己动手合成器的 PCM 数据中,然后将其转换回字节并通过 SourceDataLine 输出。
这很麻烦,你可能不想走那条路,但如果你这样做了,下面是一些信息,可以帮助分解一个可能实现的各个步骤。
在开源AudioCue(第359行loadURL
方法)中可以看到加载.wav数据并将其转换为内部PCM格式。 here 是我制作的通过击键运行的实时 Java 合成器的示例(免费下载)。其中一个声音是一个简单的风琴,它只需添加四个谐波频率的正弦波即可输出 PCM 音频数据。如果您想进入其他形式的合成但更多地参与,则可以制作其他声音。
(IDK 如何转换来自 MIDI 控制的合成器的数据,除非可以识别 TargetDataLine,并且来自它的数据转换为 PCM,类似于在 AudioCue 源示例中从 AudioInputStream 读取时使用的转换。)
给定两个 PCM 源,两者可以使用加法实时混合,转换为字节并通过单个 SourceDataLine 输出(参见第 1387 行 convertBufferToAudioBytes
方法)。如果您在贡献者不播放时输入零,则 SourceDataLine 可以无限期地保持运行。 SDL 大部分时间都处于阻塞状态,因为音频数据处理比系统消耗的速率快得多,因此使用的 CPU 很少。
【讨论】:
感谢您的明确答复。当更多的动态“混合”参与其中时,PCM 确实似乎是一种好方法。我先试试多线程的方式。以上是关于在 Java 中同时播放 .mp3 和一系列音符 (MIDI)的主要内容,如果未能解决你的问题,请参考以下文章