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

标签 android audio java-native-interface midi javax.sound.midi

我正在尝试在 Android 中加载和使用 java 的虚拟(软)合成器。我读了格维尔 jar 将用于此。
其他积木是 javax-声音 在我的项目中作为 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'
}
代码的问题区域
代码 1
MidiSystem.getMidiDeviceInfo().size    //results in an empty array in all cases
一些答案表明仅包含 gervill jar 就足以进行自动检测。
但是因为这对我不起作用,所以我写了这个
代码 2
var synth = SoftSynthesizer() as Synthesizer
        MidiSystem.addSynthesizer(synth)
我得到这个编译错误
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 
代码 3
var synth = MidiSystem.getSynthesizer()
synth?.open()
如上所述包含到 gradle,
这是没有代码 2 的运行时错误
Caused by: jp.kshoji.javax.sound.midi.MidiUnavailableException: Synthesizer not found
        at jp.kshoji.javax.sound.midi.MidiSystem.getSynthesizer(MidiSystem.java:323)
我关注了https://stackoverflow.com/a/38749847/1029110用于添加 aar/jar 文件
但是,虽然 gervill 需要 javax.sound,但还没有在模块依赖 gradle 中相互链接(应该/如何做到这一点?)
最终目标是加载和播放 soundfont 文件。
尽可能避免使用 native 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()
这提供了 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) 
代码 4:
jp.kshoji.javax.sound.midi.MidiSystem.getSoundbank(File("soundfont.sf2"))
失败
Caused by: java.lang.UnsupportedOperationException: not implemented.
    at jp.kshoji.javax.sound.midi.MidiSystem.getSoundbank(MidiSystem.java:277)
我已经检查了 Java for windows 版本的源代码。没有使用 getSoundbank 的文件覆盖或实现。
修复和 future 的步骤?

最佳答案

我理解的解决方案

代码 3。

github.com/KyoSherlock/MidiDriver是具有 com.sun.media.sound & jp\kshoji\javax\sound\midi 相同内容的 android 就绪代码。还修剪以排除不需要的类。

其他 midi 驱动程序喜欢

  • https://github.com/billthefarmer/mididriver
  • https://github.com/pedrolcl/android/tree/master/NativeGMSynth

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

    这个答案有帮助 https://stackoverflow.com/a/56700883/1029110

    代码 4。

    调用加载音库应通过 SF2SoundBank 而不是通过 MidiSystem.getSoundbank(soundFontFile)
    val sf = SF2Soundbank(assets.open("SmallTimGM6mb.sf2"))
    

    代码 1。

    对于通过电话扬声器产生声音可能并不重要,因为即使是 KyoSherlock 运行样本也返回 0

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

    关于android - Android中的虚拟合成器(基于jar) - 原生jni?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59547587/

    相关文章:

    android - Android Studio 中预建的 C 库

    我可以将 native 原始类型转换为 JNI 原始类型而不用担心字节顺序吗?

    android - 如何处理 Android MediaCodec 解码器的第一个输出字节缓冲区?

    android - 如何在不使用第 3 方应用程序的情况下在 Android 中阅读 Pdf?

    android - onNewIntent 没有被调用 - 只是每隔两次?

    Android 房间数据库 - 不确定如何将 Cursor 转换为此方法的返回类型

    vb.net - VB.NET通过音频循环

    ios - 转到类(class)时mp3播放失败

    java - 如何在java中访问C++库(DLL)的方法

    android - Root Android - 在 root 拥有的目录中创建和读取文件