我正在开发一个耳部训练应用程序,希望让用户决定要识别的声音类型(不同的乐器,合成声音等)
因此,作为“虚拟声音”,我会在SoundPool中加载类似声纳的ping:
open class PingSoundPool(context: Context) {
open var mAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_GAME)
.build()
open var mSoundPool = SoundPool.Builder()
.setMaxStreams(9)
.setAudioAttributes(mAttributes)
.build()
open var babping = mSoundPool.load(context, R.raw.ab830ping, 1)
open var aaping = mSoundPool.load(context, R.raw.a220ping, 1)
open var abbping = mSoundPool.load(context, R.raw.bb233ping, 1)
open var abping = mSoundPool.load(context, R.raw.b247ping, 1)
[and others]
open fun loadPings(note: Int) {
println(note.toString())
if (note == 0) {}
if(note == 1)
mSoundPool.play(acping, 2.55f, 2.55f, 1, 0, 1f)
if(note == 2)
mSoundPool.play(adbping, 2.5f, 2.5f, 1, 0, 1f)
if(note == 3)
mSoundPool.play(adping, 2.45f, 2.45f, 1, 0, 1f)
if(note == 4)
mSoundPool.play(aebping, 2.4f, 2.4f, 1, 0, 1f)
[and so on]
}
现在,我可以在自己的活动中访问它了
companion object {
lateinit var pingSoundPool: PingSoundPool
}
然后在onCreate中进行pingSoundPool = PingSoundPool(this)
像这样,我可以使用FullscreenActivity.pingSoundPool.loadPings(note: Int)
现在,当我想更改声音时出现问题。第一步是创建一个首选项,给我一个带有所需声音的弦(“砰”,“乒乓”,“长笛”,“小提琴”等)。第二步是获取所述字符串并相应地加载SoundPool。
现在,如果我尝试放这个-
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val pingsound = sharedPreferences.getString("pingsound", "")
if(pingsound == "ping"){
open var babping = mSoundPool.load(context, R.raw.ab830ping, 1)
open var aaping = mSoundPool.load(context, R.raw.a220ping, 1)
open var abbping = mSoundPool.load(context, R.raw.bb233ping, 1)
open var abping = mSoundPool.load(context, R.raw.b247ping, 1)
[etc]
}
如果相反,我只是复制整个课程的内容,然后像这样新建一个课程
class PongSoundPool(context: Context): PingSoundPool(context) {
override var mAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_GAME)
.build()
override var mSoundPool = SoundPool.Builder()
.setMaxStreams(9)
.setAudioAttributes(mAttributes)
.build()
open var babping = mSoundPool.load(context, R.raw.ab830pong, 1)
open var aaping = mSoundPool.load(context, R.raw.a220pong, 1)
open var abbping = mSoundPool.load(context, R.raw.bb233pong, 1)
open var abping = mSoundPool.load(context, R.raw.b247pong, 1)
并在这样的活动中分配pingSoundPool
的值
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
val pingsound = sharedPreferences.getString("pingsound", "")
when (pingsound) {
"ping" -> pingSoundPool = PingSoundPool(this)
"pong" -> pingSoundPool = PongSoundPool(this)
}
然后,一旦我将首选项更改为“ pong”,就什么也没有发生。重新启动应用程序时,出现运行时错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.FullscreenActivity}: java.lang.IllegalArgumentException: Invalid null AudioAttributes
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalArgumentException: Invalid null AudioAttributes
at android.media.SoundPool$Builder.setAudioAttributes(SoundPool.java:601)
at com.example.PingSoundPool.<init>(PingSoundPool.kt:16)
at com.example.PongSoundPool.<init>(PongSoundPool.kt:7)
at com.example.FullscreenActivity.onCreate(FullscreenActivity.kt:97)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
它在PingSoundPool中指向的行是:.setAudioAttributes(mAttributes)
现在我不知道如何实现此目的。有人得到帮助了吗?
答案 0 :(得分:0)
您的第一次崩溃是由于不正确的继承。如果您已经在var mAttributes
中实现了PingSoundPool
和var mSoundPool,请不要在PongSoundPool
上覆盖它。另外,您可以通过不将PingSoundPool
创建为父类来改善体系结构。但是BaseSoundPool
具有最终属性mAttributes
和mSoundPool
,并且具有抽象方法fun play(note: Int)
abstract class BaseSoundPool(val context: Context) {
protected var loadedSoundChannels: IntArray? = null
private val attributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_GAME)
.build()
final val soundPool = SoundPool.Builder()
.setMaxStreams(9)
.setAudioAttributes(attributes)
.build()
fun load(rawSoundIds: IntArray) {
loadedSoundChannels?.run { unload(this) } // todo implement unload fun by yourself
loadedSoundChannels = IntArray(rawSoundIds.size) {
soundPool.load(context, rawSoundIds[it], 1)
}
}
abstract fun play(note: Int)
}
class PingSoundPool(context: Context) : BaseSoundPool(context) {
override fun play(note: Int) {
loadedSoundChannels?.getOrNull(note)?.let {
soundPool.play(note, 1f, 1f, 1, 0, 1f);
}
}
}
还要记住,SoundPool.load
是异步操作,因此您不能在加载后立即调用播放。同样,在加载新的声音数据时,还应该卸载以前加载的声音。
也许您会发现我对SoundPool的实现很有用,这在不同的API上更容易预测。