使用软件合成器将 MIDI 文件转换为原始音频

Posted

技术标签:

【中文标题】使用软件合成器将 MIDI 文件转换为原始音频【英文标题】:Converting MIDI file to raw audio using a software synth 【发布时间】:2013-12-18 15:24:48 【问题描述】:

我正在尝试直接从我的 android 应用程序动态生成一个小的 MP4 音频+视频文件。

我原来的进攻计划:

    用户输入一些基本的歌曲数据(和弦进行等),应用程序构建一个 MIDI 文件。

    系统为每个和弦构建和弦图,并使用 MIDI 阅读器生成与 MIDI 同步的动画帧数组

    将 MIDI 转换为原始 PCM 音频数据

    将原始音频应用于动画帧 - 并将音频和视频帧编码为 MP4

    使用标准播放控件向用户提供生成的 MP4 视频。

应用程序已经根据用户输入(包括速度、乐器、音符等)构建了 MIDI 文件。这部分很容易完成,并且 MIDI 文件正在正确生成。这个 MIDI 可以在 Android 的 MediaPlayer 中正常播放。 (第 1 步)

通过回读 MIDI 文件并交叉引用序列中每个和弦的静态位图列表,也可以正确创建动画帧。这些帧将成为视频......但一开始将没有音频。 (第 2 步)

如您所见,Android MIDI 延迟问题对我来说并不是什么大问题,因为我不是在创建实时合成器应用程序...我只是想将 MIDI 转换为可以然后混合成一个已经定时到原始 MIDI 的视频。 (第 3 步)


我遇到的问题是第 3 步。

我了解我需要使用软件 MIDI 合成器来获取将由一系列 MIDI 事件产生的实际音频输出。但是,如何使其正常工作已成为主要障碍。我不关心生成的音频的精确质量,只是它与人们在使用通用设备(ala Gravis soundfonts 或内置 Sovinox 声音等)的通用 MIDI 样本时所期望的非常匹配。

所以...

    Android MIDI Lib

    Android Midi Driver using Sonivox EAS Library

我的第一次尝试是使用上述两个项目...将它们混合在一起,以便将 MIDI 文件转换为原始 PCM 数据缓冲区...。它还没有那么顺利。

midi 库 (1) 使用实时侦听器读取 MIDI 文件,并将事件发送到 Midi 驱动程序 (2),后者播放板载合成器生成的原始 PCM 数据。

(注意:对驱动程序进行了一些调整,以便存储整个缓冲区并仅在 MIDI 读取器完成后返回。这也意味着整个过程花费的时间等于歌曲的长度转换它,因为我们是实时“听”的。)

我还没有像我希望的那样让它工作。我想让这尽可能简单,如果可能的话,我更喜欢使用开源项目。如果它能够在不依赖实时监听器的情况下做到这一点会更好。


我一直在考虑的其他一些库和工具(但可能有点矫枉过正):

    Pure Data Library for Android

    MidiSheetMusic App (with source)

    Synthesis ToolKit in C++ (STK)

    Music Synth for Android

    Crimson SoftSynth

更多的竞争者(还没有做太多的研究):

jFugue/胆小/大胆/fluidSynth/cSound/jMusic/JSyn/Gervill/Softonic/Cau​​stic/LibGDX/JetPlayer/OpenSL-ES


我的问题是:

我在上述项目中的工作是否正确?我对 MIDI->PCM 转换比较陌生,所以我想确保我没有完全遗漏一些东西。

如果不是,我应该如何将 MIDI 文件转换为某种音频格式,然后可用于创建 MP4(或任何视频播放格式)?

是否有其他开源项目可能有助于这项使用 Android 转换 MIDI 2 原始音频波形的任务?

是否有任何此类任务的示例已经为在 Android 上使用而编写? (即已经移植用于 Android JNI 等)

我希望我完全错过了一些让这成为一项微不足道的任务......我的假设是这将需要一些严肃的黑客攻击和 JNI 功夫。

如果需要的话,我愿意走艰难的道路。任何和所有的建议都将不胜感激。

【问题讨论】:

我能够让原始的 MidiDriver 返回整个缓冲区,但我仍然认为这不是完成任务的最佳方式。我目前正在查看以下函数:EAS_OpenFile 以及它在 Android 的媒体播放器类中的使用方式:android.googlesource.com/platform/frameworks/base/+/… 处理 MIDI 文件(而不是实时流式传输)的新 MidiDriver 类可能是更好的解决方案。我不熟悉 JNI 中的 HostWrappers 或文件句柄,所以我有一些研究要做。 只是好奇你是否设法找到解决方案 这是一个很好的问题,我也一直找不到答案。我假设在 Android 6.0 Marshmallow 对 MIDI 的支持下,会有一个预打包的合成器供开发人员使用,但可惜,没有运气。如果有人对此有答案,请告诉我。 【参考方案1】:

我不是 Android 用户,但我尝试了很多从 MIDI 生成 WAV 文件的方法,而且我对这项任务感到更满意,使用 FluidSynth,它似​​乎可以作为 Android 库使用,并且是另一个 *** 问题的重点:Using Fluidsynth to play notes from SoundFonts on Android。

你只需要了解声音字体(搜索网络很容易告诉你)并选择一个不太大的好字体(否则你可能会出现内存不足的问题)。

还要检查声音字体是否涵盖了您想要演奏的所有乐器。

【讨论】:

【参考方案2】:

如果您在 JS 或 Node 环境中运行,您应该能够使用 mudcube 的 MIDI.js(或我的 ES6 端口作为 midicube)使用 Player 对象将 MIDI 转换为 webaudio 输出并轻松播放。或者,如果您想保存它,您可以捕获流并将其转换为任意数量的格式(可能包括 mp3,但我从未尝试过)。如果时间不是转换的关键,第二部分应该很容易,但是转换需要 MIDI 的运行时间。应该可以加快播放速度和样本的播放速度,使转换以 2 或 4 倍的速度发生,然后再减慢文件,但我没有尝试过。

如果您对库有较低级别的访问权限,@Hibou57 建议使用 FluidSynth 是最好的。

无论哪种方式,您都需要一些声音字体。 Fluid-GM 适用于较低质量但可接受的声音。

【讨论】:

以上是关于使用软件合成器将 MIDI 文件转换为原始音频的主要内容,如果未能解决你的问题,请参考以下文章

Python:midi 到音频流

关于MIDI文件

如何使用流体合成器将单个 midi 通道导出为 wav?

基本软件合成器的延迟随着时间的推移而增长

如何将组成文件的原始位显示为位图图像? [关闭]

怎么把文字转换成音频?