Android 中的虚拟合成器(基于 jar) - 原生 jni?

Rah*_*ale 6 audio midi java-native-interface android javax.sound.midi

我正在尝试在 Android 中加载和使用 java 的虚拟(软)合成器。我读到Gervill jar 将用于此目的。其他构建块是javax-sound作为 aar 文件存在于我的项目中(因为它不存在于 Android 的修剪 Java 包中)

Gradle 文件包含是

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.0"
    dataBinding {
        enabled = true
    }
    defaultConfig {
        applicationId "com.mmm.ttt"
        minSdkVersion 18
        targetSdkVersion 29
        multiDexEnabled true
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(path: ':javax-sound')
    implementation project(path: ':gervilljar')         // This is folder name at project root folder level containing gervill.jar
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:multidex:1.0.3'
}
Run Code Online (Sandbox Code Playgroud)

代码的问题区域

代码 1

MidiSystem.getMidiDeviceInfo().size    //results in an empty array in all cases
Run Code Online (Sandbox Code Playgroud)

一些答案表明仅包含 gervill jar 就足以进行自动检测。但是因为这对我不起作用,所以我写了这个

代码 2

var synth = SoftSynthesizer() as Synthesizer
        MidiSystem.addSynthesizer(synth)
Run Code Online (Sandbox Code Playgroud)

我为此收到编译错误

Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class com.sun.media.sound.SoftSynthesizer, unresolved supertypes: com.sun.media.sound.ReferenceCountingDevice
    class com.sun.media.sound.AudioSynthesizer, unresolved supertypes: javax.sound.midi.Synthesizer 
Run Code Online (Sandbox Code Playgroud)

代码 3

var synth = MidiSystem.getSynthesizer()
synth?.open()
Run Code Online (Sandbox Code Playgroud)

包含上面的gradle,这是没有代码2的运行时错误

Caused by: jp.kshoji.javax.sound.midi.MidiUnavailableException: Synthesizer not found
        at jp.kshoji.javax.sound.midi.MidiSystem.getSynthesizer(MidiSystem.java:323)
Run Code Online (Sandbox Code Playgroud)

我按照/sf/answers/2712489321/添加 aar/jar 文件
但是,虽然 gervill 需要 javax.sound,但还没有在模块依赖项 gradle 中相互链接(应该/如何做?)

最终目标是加载和播放声音字体文件。如果可能,避免使用原生 jni 代码。

编辑

确定了 1 个问题。Gervill.jar 不足以无错误地工作。所以我从 com.sun.media.sound.* 中挑选了一些其他类并编译成新的 jar。现在代码 2 ( unresolved supertypes)中的错误已经消失了。

下一个试验是包括 Android MIDI 服务

val midiManager = context.getSystemService(Context.MIDI_SERVICE) as android.media.midi.MidiManager
midiManager.getDevices()
Run Code Online (Sandbox Code Playgroud)

这提供了 2 个服务,具体取决于安装在移动设备上的外部应用程序。但是它们无论如何都没有链接到软合成器。  
所以,代码 1 仍然有 MidiDeviceInfo 的空数组。  
代码 3 的一部分:synth?.open()仍然严重失败,但出现了新的错误。 (目前卡在这里)

Caused by: jp.kshoji.javax.sound.midi.MidiUnavailableException: Can not open line
        at com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1132)
        at com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1036)
Caused by: java.lang.IllegalArgumentException: No line matching interface jp.kshoji.SourceDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian is supported.
        at jp.kshoji.javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:475)
        at jp.kshoji.javax.sound.sampled.AudioSystem.getSourceDataLine(AudioSystem.java:602)
        at com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1066)
        at com.sun.media.sound.SoftSynthesizer.open(SoftSynthesizer.java:1036) 
Run Code Online (Sandbox Code Playgroud)

代码 4:

jp.kshoji.javax.sound.midi.MidiSystem.getSoundbank(File("soundfont.sf2"))
Run Code Online (Sandbox Code Playgroud)

失败

Caused by: java.lang.UnsupportedOperationException: not implemented.
    at jp.kshoji.javax.sound.midi.MidiSystem.getSoundbank(MidiSystem.java:277)
Run Code Online (Sandbox Code Playgroud)

我已经检查了 Windows 版本源代码的 Java。没有覆盖或实现文件以使用 getSoundbank。

修复和未来的步骤?

Rah*_*ale 0

我理解的解决方案

代码 3。

github.com/KyoSherlock/MidiDriver是 android 就绪代码,其中包含与 com.sun.media.sound 和 jp\kshoji\javax\sound\midi 相同的内容。还进行了修剪以排除不需要的类。

其他 MIDI 驱动程序如

基于本机 C/C++ 代码,我一直避免使用它。

这个答案有帮助/sf/answers/3969061841/

代码 4。

调用加载音库应通过 SF2SoundBank 完成,而不是通过 MidiSystem.getSoundbank(soundFontFile) 完成

val sf = SF2Soundbank(assets.open("SmallTimGM6mb.sf2"))
Run Code Online (Sandbox Code Playgroud)

代码 1。

对于通过手机扬声器产生声音可能并不重要,因为即使是 KyoSherlock 运行示例也会返回 0

深入阅读可以在这里完成 :http://jsresources.sourceforge.net/faq_midi.html