mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 08:19:33 +00:00
minor fmod cleanup
This commit is contained in:
3 files changed
+72
-54
No files matched your search
@@ -1,26 +1,32 @@
|
|||||||
package org.fmod
|
package org.fmod
|
||||||
|
|
||||||
|
import android.media.AudioAttributes
|
||||||
|
import android.media.AudioFormat
|
||||||
|
import android.media.AudioManager
|
||||||
import android.media.AudioTrack
|
import android.media.AudioTrack
|
||||||
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
||||||
class AudioDevice {
|
class AudioDevice {
|
||||||
private var mTrack: AudioTrack? = null
|
private var mTrack: AudioTrack? = null
|
||||||
private fun fetchChannelConfigFromCount(i: Int): Int {
|
private fun fetchChannelConfigFromCount(speakerCount: Int): Int {
|
||||||
if (i == 1) {
|
return when (speakerCount) {
|
||||||
return 2
|
1 -> AudioFormat.CHANNEL_OUT_MONO
|
||||||
|
2 -> AudioFormat.CHANNEL_OUT_STEREO
|
||||||
|
6 -> AudioFormat.CHANNEL_OUT_5POINT1
|
||||||
|
8 -> AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
|
||||||
|
else -> AudioFormat.CHANNEL_INVALID
|
||||||
}
|
}
|
||||||
if (i == 2) {
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
if (i == 6) {
|
|
||||||
return 252
|
|
||||||
}
|
|
||||||
return if (i == 8) 6396 else 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init(i: Int, i2: Int, i3: Int, i4: Int): Boolean {
|
fun init(channelCount: Int, sampleRateInHz: Int, sampleSize: Int, sampleCount: Int): Boolean {
|
||||||
val fetchChannelConfigFromCount = fetchChannelConfigFromCount(i)
|
val channelConfig = fetchChannelConfigFromCount(channelCount)
|
||||||
val minBufferSize = AudioTrack.getMinBufferSize(i2, fetchChannelConfigFromCount, 2)
|
val minBufferSize = AudioTrack.getMinBufferSize(
|
||||||
|
sampleRateInHz,
|
||||||
|
channelConfig,
|
||||||
|
AudioFormat.ENCODING_PCM_16BIT
|
||||||
|
)
|
||||||
|
|
||||||
if (minBufferSize < 0) {
|
if (minBufferSize < 0) {
|
||||||
Log.w(
|
Log.w(
|
||||||
"fmod",
|
"fmod",
|
||||||
@@ -29,11 +35,33 @@ class AudioDevice {
|
|||||||
} else {
|
} else {
|
||||||
Log.i("fmod", "AudioDevice::init : Min buffer size: $minBufferSize bytes")
|
Log.i("fmod", "AudioDevice::init : Min buffer size: $minBufferSize bytes")
|
||||||
}
|
}
|
||||||
val i5 = i3 * i4 * i * 2
|
|
||||||
val i6 = if (i5 > minBufferSize) i5 else minBufferSize
|
val realBufferSize = sampleSize * sampleCount * channelCount * 2
|
||||||
Log.i("fmod", "AudioDevice::init : Actual buffer size: $i6 bytes")
|
val bufferSize = minBufferSize.coerceAtLeast(realBufferSize)
|
||||||
|
Log.i("fmod", "AudioDevice::init : Actual buffer size: $bufferSize bytes")
|
||||||
return try {
|
return try {
|
||||||
val audioTrack = AudioTrack(3, i2, fetchChannelConfigFromCount, 2, i6, 1)
|
val attributes = AudioAttributes.Builder()
|
||||||
|
.setUsage(AudioAttributes.USAGE_GAME)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val format = AudioFormat.Builder()
|
||||||
|
.setChannelMask(channelConfig)
|
||||||
|
.setSampleRate(sampleRateInHz)
|
||||||
|
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val audioTrackBuilder = AudioTrack.Builder()
|
||||||
|
.setAudioAttributes(attributes)
|
||||||
|
.setAudioFormat(format)
|
||||||
|
.setBufferSizeInBytes(bufferSize)
|
||||||
|
.setTransferMode(AudioTrack.MODE_STREAM)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
audioTrackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY)
|
||||||
|
}
|
||||||
|
|
||||||
|
val audioTrack = audioTrackBuilder.build()
|
||||||
|
|
||||||
mTrack = audioTrack
|
mTrack = audioTrack
|
||||||
try {
|
try {
|
||||||
audioTrack.play()
|
audioTrack.play()
|
||||||
@@ -44,7 +72,7 @@ class AudioDevice {
|
|||||||
mTrack = null
|
mTrack = null
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
} catch (unused2: IllegalArgumentException) {
|
} catch (_: IllegalArgumentException) {
|
||||||
Log.e("fmod", "AudioDevice::init : AudioTrack creation caused IllegalArgumentException")
|
Log.e("fmod", "AudioDevice::init : AudioTrack creation caused IllegalArgumentException")
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -60,7 +88,7 @@ class AudioDevice {
|
|||||||
mTrack = null
|
mTrack = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun write(sArr: ShortArray?, i: Int) {
|
fun write(sArr: ShortArray, size: Int) {
|
||||||
mTrack!!.write(sArr!!, 0, i)
|
mTrack?.write(sArr, 0, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,9 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
|
import android.media.AudioDeviceInfo
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@@ -23,13 +25,11 @@ object FMOD {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun init(context: Context?) {
|
fun init(context: Context?) {
|
||||||
gContext = context
|
gContext = context
|
||||||
if (context != null) {
|
gContext?.registerReceiver(
|
||||||
gContext!!.registerReceiver(
|
|
||||||
gPluginBroadcastReceiver,
|
gPluginBroadcastReceiver,
|
||||||
IntentFilter("android.intent.action.HEADSET_PLUG")
|
IntentFilter(Intent.ACTION_HEADSET_PLUG)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun close() {
|
fun close() {
|
||||||
@@ -65,22 +65,14 @@ object FMOD {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun lowLatencyFlag(): Boolean {
|
fun lowLatencyFlag(): Boolean {
|
||||||
if (Build.VERSION.SDK_INT < 5) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = gContext ?: return false
|
val context = gContext ?: return false
|
||||||
return context.packageManager.hasSystemFeature("android.hardware.audio.low_latency")
|
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun proAudioFlag(): Boolean {
|
fun proAudioFlag(): Boolean {
|
||||||
if (Build.VERSION.SDK_INT < 5) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = gContext ?: return false
|
val context = gContext ?: return false
|
||||||
return context.packageManager.hasSystemFeature("android.hardware.audio.pro")
|
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -90,26 +82,18 @@ object FMOD {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getOutputSampleRate(): Int {
|
fun getOutputSampleRate(): Int {
|
||||||
if (Build.VERSION.SDK_INT < 17) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = gContext ?: return 0
|
val context = gContext ?: return 0
|
||||||
val audioService = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
val audioService = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
val property = audioService.getProperty("android.media.property.OUTPUT_SAMPLE_RATE")
|
val property = audioService.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
|
||||||
|
|
||||||
return property?.toInt() ?: 0
|
return property?.toInt() ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getOutputBlockSize(): Int {
|
fun getOutputBlockSize(): Int {
|
||||||
if (Build.VERSION.SDK_INT < 17) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = gContext ?: return 0
|
val context = gContext ?: return 0
|
||||||
val audioService = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
val audioService = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
val property = audioService.getProperty("android.media.property.OUTPUT_FRAMES_PER_BUFFER")
|
val property = audioService.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
|
||||||
|
|
||||||
return property?.toInt() ?: 0
|
return property?.toInt() ?: 0
|
||||||
}
|
}
|
||||||
@@ -118,7 +102,11 @@ object FMOD {
|
|||||||
fun isBluetoothOn(): Boolean {
|
fun isBluetoothOn(): Boolean {
|
||||||
val context = gContext ?: return false
|
val context = gContext ?: return false
|
||||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
return audioManager.isBluetoothA2dpOn || audioManager.isBluetoothScoOn
|
|
||||||
|
val devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
|
||||||
|
return devices.any {
|
||||||
|
it.type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP || it.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.fmod
|
package org.fmod
|
||||||
|
|
||||||
|
import android.media.MediaCodec
|
||||||
import android.media.MediaCrypto
|
import android.media.MediaCrypto
|
||||||
import android.media.MediaDataSource
|
import android.media.MediaDataSource
|
||||||
import android.media.MediaExtractor
|
import android.media.MediaExtractor
|
||||||
@@ -14,8 +15,7 @@ class MediaCodec {
|
|||||||
|
|
||||||
var mCodecPtr: Long = 0
|
var mCodecPtr: Long = 0
|
||||||
private var mCurrentOutputBufferIndex = -1
|
private var mCurrentOutputBufferIndex = -1
|
||||||
private var mDataSourceProxy: Any? = null
|
private var mDecoder: MediaCodec? = null
|
||||||
private var mDecoder: android.media.MediaCodec? = null
|
|
||||||
private var mExtractor: MediaExtractor? = null
|
private var mExtractor: MediaExtractor? = null
|
||||||
private var mInputBuffers: Array<ByteBuffer>? = null
|
private var mInputBuffers: Array<ByteBuffer>? = null
|
||||||
private var mInputFinished = false
|
private var mInputFinished = false
|
||||||
@@ -57,7 +57,7 @@ class MediaCodec {
|
|||||||
)
|
)
|
||||||
if (string == "audio/mp4a-latm") {
|
if (string == "audio/mp4a-latm") {
|
||||||
return try {
|
return try {
|
||||||
mDecoder = android.media.MediaCodec.createDecoderByType(string)
|
mDecoder = MediaCodec.createDecoderByType(string)
|
||||||
mExtractor!!.selectTrack(i2)
|
mExtractor!!.selectTrack(i2)
|
||||||
mDecoder!!.configure(trackFormat, null as Surface?, null as MediaCrypto?, 0)
|
mDecoder!!.configure(trackFormat, null as Surface?, null as MediaCrypto?, 0)
|
||||||
mDecoder!!.start()
|
mDecoder!!.start()
|
||||||
@@ -100,7 +100,7 @@ class MediaCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun read(bArr: ByteArray?, i: Int): Int {
|
fun read(bArr: ByteArray, i: Int): Int {
|
||||||
var dequeueInputBuffer = 0
|
var dequeueInputBuffer = 0
|
||||||
val i2 =
|
val i2 =
|
||||||
if (!mInputFinished || !mOutputFinished || mCurrentOutputBufferIndex != -1) 0 else -1
|
if (!mInputFinished || !mOutputFinished || mCurrentOutputBufferIndex != -1) 0 else -1
|
||||||
@@ -129,14 +129,14 @@ class MediaCodec {
|
|||||||
mCurrentOutputBufferIndex = dequeueOutputBuffer
|
mCurrentOutputBufferIndex = dequeueOutputBuffer
|
||||||
mOutputBuffers!![dequeueOutputBuffer].limit(bufferInfo.size)
|
mOutputBuffers!![dequeueOutputBuffer].limit(bufferInfo.size)
|
||||||
mOutputBuffers!![dequeueOutputBuffer].position(bufferInfo.offset)
|
mOutputBuffers!![dequeueOutputBuffer].position(bufferInfo.offset)
|
||||||
} else if (dequeueOutputBuffer == -3) {
|
} else if (dequeueOutputBuffer == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
|
||||||
mOutputBuffers = mDecoder!!.outputBuffers
|
mOutputBuffers = mDecoder!!.outputBuffers
|
||||||
} else if (dequeueOutputBuffer == -2) {
|
} else if (dequeueOutputBuffer == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"fmod",
|
"fmod",
|
||||||
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned MediaCodec.INFO_OUTPUT_FORMAT_CHANGED " + mDecoder!!.outputFormat
|
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned MediaCodec.INFO_OUTPUT_FORMAT_CHANGED " + mDecoder!!.outputFormat
|
||||||
)
|
)
|
||||||
} else if (dequeueOutputBuffer == -1) {
|
} else if (dequeueOutputBuffer == MediaCodec.INFO_TRY_AGAIN_LATER) {
|
||||||
Log.d(
|
Log.d(
|
||||||
"fmod",
|
"fmod",
|
||||||
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned MediaCodec.INFO_TRY_AGAIN_LATER."
|
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned MediaCodec.INFO_TRY_AGAIN_LATER."
|
||||||
@@ -147,7 +147,7 @@ class MediaCodec {
|
|||||||
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned $dequeueOutputBuffer"
|
"MediaCodec::read : MediaCodec::dequeueOutputBuffer returned $dequeueOutputBuffer"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (bufferInfo.flags and 4 !== 0) {
|
if (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
|
||||||
mOutputFinished = true
|
mOutputFinished = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,13 +188,15 @@ class MediaCodec {
|
|||||||
}
|
}
|
||||||
val bArr = ByteArray(1024)
|
val bArr = ByteArray(1024)
|
||||||
while (i3 > 0) {
|
while (i3 > 0) {
|
||||||
i3 -= read(bArr, Math.min(1024, i3))
|
i3 -= read(bArr, 1024.coerceAtMost(i3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
external fun fmodGetSize(j: Long): Long
|
external fun fmodGetSize(j: Long): Long
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
external fun fmodReadAt(j: Long, j2: Long, bArr: ByteArray?, i: Int, i2: Int): Int
|
external fun fmodReadAt(j: Long, j2: Long, bArr: ByteArray?, i: Int, i2: Int): Int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user