听众模式_in_communication降低了声音质量并引起crack啪作响/弹出声音
问题的描述:
当应用程序通过蓝牙耳机连接时,我正在启动audiomanager.startbluetoothsco()
。您可以检查下面的代码。该连接效果很好,但是我对MediaPlayer播放的crack啪声有疑问。每当播放动作声音时,质量不好或crack啪作响的声音就会发生。 (例如r.raw.record_start,r.raw.success_action,r.raw.failure_action)
我用来测试的设备:
- Aftershokx和Jabra Evolve 65
- ,Samsung A50
Samsung A52,Samsung A50,Samsung A50 VE尝试了吗?
- 我尝试将
audiomanager.mode = audiomanager.mode_in_communication
更改为audiomanager.mode_in_call或audiomanager.mode_normal。
- 更改为Mode_in_call不会更改
audiomanager.mode
。该值保持为0,是sode_normal。
- 更改为Mode_normal仅在Samsung A52上起作用。没有crack啪声听起来一切正常。这就是我要实现的目标,
- 但是所有其他手机都切换到其他流或其他东西。这就是为什么我听不到任何媒体声音的原因。
- 假设我使用像素3,并与jabra在sode_normal中相连的65。我再也听不到任何类型的媒体声音,包括YouTube,Spotify和System Sounds等其他应用程序,但它可以在Mode_in_communication和Crackling Sound中起作用。
我试图更改MediaPlayer的AudioAttributes,但质量仍然不好。
val actionsound = if(triggerErrorearcon)r.raw.failure_action else if(longRecorDingbreak)r.raw.success_action else r.raw.record_start Val MD = MediaPlayer.Create(上下文,Actionsound) val streamType = if(audiodevicemanager.headsetconnected)audiomanager.stream_voice_call MD.SetaudioAttributes( AudioAttributes.builder() .setlegacystreamtype(streamType) .setContentType(AudioAttributes.Content_Type_music) 。建造()) md.play()
可能的解决方案?
- 我不知道如何修复
audiomanager.mode
或AudoManager的其他某些属性。 - 继续使用Mode_in_communication,但可以解决MediaPlayer属性的修复,以禁用蓝牙设备上的声音质量不佳。
- 从这一点开始,我什么也没想到。希望您能帮助我解决这个问题,谢谢。
AudiodeviceManager.kt:
class AudioDeviceManager(val context: Context) {
internal val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
internal val headsetConnectedSubject = BehaviorSubject.createDefault(false)
internal val headsetConnected: Boolean get() = headsetConnectedSubject.value ?: false
private val intentFilter = IntentFilter().apply { addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) }
private val audioDeviceCallback = object: AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesAdded(addedDevices)
updateBluetoothHeadsetState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesRemoved(removedDevices)
updateBluetoothHeadsetState()
}
}
private val scoReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1) == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// SCO now connected
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = false
audioManager.isBluetoothScoOn = true
}
}
}
fun start() {
if (headsetConnected.not())
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null)
}
fun stop(unregisterAudioDeviceCallback: Boolean = false) {
if (unregisterAudioDeviceCallback)
unregisterDeviceCallback()
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
private fun unregisterDeviceCallback() = audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
fun updateBluetoothHeadsetState() {
val headset = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)?.firstOrNull { it.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO }
val headsetConnected = headset != null
headsetConnectedSubject.onNext(headsetConnected)
if (headsetConnected) {
audioManager.startBluetoothSco()
context.registerReceiver(scoReceiver, intentFilter)
} else {
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
}
}
在应用程序中播放动作声音:
MediaPlayer.create(context, R.raw.record_start)
.play()
.subscribe()
.addTo(disposable)
扩展功能:
fun MediaPlayer.play(): Completable {
return Completable.create { emitter ->
var isCancelled = false
emitter.setCancellable {
isCancelled = true
}
setOnCompletionListener {
GlobalScope.launch {
// release the sound a bit later. Listener is triggering so fast!
delay(3000)
it.release()
}
if (isCancelled) { return@setOnCompletionListener }
emitter.onComplete()
}
start()
}
}
Description of the problem:
When the app is connected through Bluetooth headsets, I'm starting the audioManager.startBluetoothSco()
. You can check the code below. The connection works well, but I have a problem with the crackling sounds that are played by MediaPlayer. Whenever an action sound is played, the quality is bad or a crackling sound happens. (eg. R.raw.record_start, R.raw.success_action, R.raw.failure_action)
Devices that I used to test:
- OpenComm by AfterShokx and Jabra Evolve 65
- Samsung A52, Samsung A50, Pixel 3, OnePlus 6 Pro
What I've tried so far?
- I tried to change
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
to AudioManager.MODE_IN_CALL or AudioManager.MODE_NORMAL.
- Changing to MODE_IN_CALL doesn't change the
audioManager.mode
. The value stays as 0 which is MODE_NORMAL.
- Changing to MODE_NORMAL only works on Samsung A52. No crackling sounds everything works perfectly. This is what I want to achieve,
- BUT all other phones switch to a different stream or something else; that's why I can't HEAR any media sounds.
- Let's say I use Pixel 3 and connected with Jabra Evolve 65 in MODE_NORMAL. I can't hear any kind of media sounds anymore including other apps like Youtube, Spotify, and system sounds, but it works in MODE_IN_COMMUNICATION with a crackling sound.
I tried to change MediaPlayer's AudioAttributes but still bad quality.
val actionSound = if (triggerErrorEarcon) R.raw.failure_action else if (longRecordingBreak) R.raw.success_action else R.raw.record_start val md = MediaPlayer.create(context, actionSound) val streamType = if (audioDeviceManager.headsetConnected) AudioManager.STREAM_VOICE_CALL else AudioManager.STREAM_MUSIC md.setAudioAttributes( AudioAttributes.Builder() .setLegacyStreamType(streamType) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build()) md.play()
Possible Solutions?
- I don't know how but fixing
audioManager.mode
or some other properties of audioManager. - Keep using MODE_IN_COMMUNICATION but a fix on MediaPlayer properties to disable bad quality of sound on Bluetooth device.
- I can't think of anything else from this point. I hope you could help me with this problem, thanks in advance.
AudioDeviceManager.kt:
class AudioDeviceManager(val context: Context) {
internal val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
internal val headsetConnectedSubject = BehaviorSubject.createDefault(false)
internal val headsetConnected: Boolean get() = headsetConnectedSubject.value ?: false
private val intentFilter = IntentFilter().apply { addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) }
private val audioDeviceCallback = object: AudioDeviceCallback() {
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesAdded(addedDevices)
updateBluetoothHeadsetState()
}
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
super.onAudioDevicesRemoved(removedDevices)
updateBluetoothHeadsetState()
}
}
private val scoReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1) == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
// SCO now connected
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = false
audioManager.isBluetoothScoOn = true
}
}
}
fun start() {
if (headsetConnected.not())
audioManager.registerAudioDeviceCallback(audioDeviceCallback, null)
}
fun stop(unregisterAudioDeviceCallback: Boolean = false) {
if (unregisterAudioDeviceCallback)
unregisterDeviceCallback()
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
private fun unregisterDeviceCallback() = audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
fun updateBluetoothHeadsetState() {
val headset = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)?.firstOrNull { it.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO }
val headsetConnected = headset != null
headsetConnectedSubject.onNext(headsetConnected)
if (headsetConnected) {
audioManager.startBluetoothSco()
context.registerReceiver(scoReceiver, intentFilter)
} else {
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
audioManager.isBluetoothScoOn = false
audioManager.stopBluetoothSco()
}
}
}
Playing an action sound in the app:
MediaPlayer.create(context, R.raw.record_start)
.play()
.subscribe()
.addTo(disposable)
Extension function:
fun MediaPlayer.play(): Completable {
return Completable.create { emitter ->
var isCancelled = false
emitter.setCancellable {
isCancelled = true
}
setOnCompletionListener {
GlobalScope.launch {
// release the sound a bit later. Listener is triggering so fast!
delay(3000)
it.release()
}
if (isCancelled) { return@setOnCompletionListener }
emitter.onComplete()
}
start()
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论