Android 中的虚拟合成器(基于 jar)- 本机 jni?
Virtual synthesizer in Android (based on jar) - native jni?
我正在尝试在 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'
}
代码的问题区域
代码 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)
我按照 添加了 aar/jar 个文件
但是,虽然 gervill 需要 javax.sound
,但还没有在模块依赖项中相互链接 gradle(Should/How 才能做到这一点?)
最终目的是加载和播放音色文件。
尽可能避免使用本机 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 的 windows 版本源代码。没有覆盖或实现文件来使用 getSoundbank。
修复和后续步骤?
我理解的解决方案
代码 3.
github.com/KyoSherlock/MidiDriver 是 android 就绪代码,它具有与 com.sun.media.sound 和 jp\kshoji\javax\sound\midi 相同的内容放在一起。还进行了修剪以排除不需要的 类.
其他 midi 驱动程序,例如
- https://github.com/billthefarmer/mididriver
- https://github.com/pedrolcl/android/tree/master/NativeGMSynth
基于本机 C/C++ 代码,我一直避免使用它。
这个回答有帮助
代码 4.
加载音库的调用应该通过 SF2SoundBank 而不是通过 MidiSystem.getSoundbank(soundFontFile)
val sf = SF2Soundbank(assets.open("SmallTimGM6mb.sf2"))
代码 1.
对于通过 phone 扬声器发出声音可能并不重要,因为即使是 KyoSherlock 运行 样本 returns 0
我正在尝试在 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'
}
代码的问题区域
代码 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)
我按照
但是,虽然 gervill 需要 javax.sound
最终目的是加载和播放音色文件。 尽可能避免使用本机 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 的 windows 版本源代码。没有覆盖或实现文件来使用 getSoundbank。
修复和后续步骤?
我理解的解决方案
代码 3.
github.com/KyoSherlock/MidiDriver 是 android 就绪代码,它具有与 com.sun.media.sound 和 jp\kshoji\javax\sound\midi 相同的内容放在一起。还进行了修剪以排除不需要的 类.
其他 midi 驱动程序,例如
- https://github.com/billthefarmer/mididriver
- https://github.com/pedrolcl/android/tree/master/NativeGMSynth
基于本机 C/C++ 代码,我一直避免使用它。
这个回答有帮助
代码 4.
加载音库的调用应该通过 SF2SoundBank 而不是通过 MidiSystem.getSoundbank(soundFontFile)
val sf = SF2Soundbank(assets.open("SmallTimGM6mb.sf2"))
代码 1.
对于通过 phone 扬声器发出声音可能并不重要,因为即使是 KyoSherlock 运行 样本 returns 0