1 Commits
Author SHA1 Message Date
sansen 53f286e407 解决默认音量过小的问题 2026-07-23 20:00:38 +08:00
@@ -55,6 +55,7 @@ class VoiceService(
private var playbackGeneration = 0L
private var activePlaybackTrack: AudioTrack? = null
@Volatile private var receiveVolume = 1.0f
@Volatile private var receiveGain = 2.5f
private val audioManager = context.getSystemService(AudioManager::class.java)
private var audioFocusRequest: AudioFocusRequest? = null
@@ -129,6 +130,11 @@ class VoiceService(
}
}
/** 设置 PCM 预增益(1.0 = 原始音量,2.5 = 默认) */
fun setReceiveGain(gain: Float) {
receiveGain = gain.coerceIn(0.5f, 5.0f)
}
fun enableReceivePlayback() {
if (speakerEnabled) forceLoudspeaker()
}
@@ -176,10 +182,12 @@ class VoiceService(
synchronized(playbackLock) { activePlaybackTrack = track }
}
val activeTrack = track ?: continue
// 应用 PCM 预增益
val gainedFrame = applyPcmGain(frame, receiveGain)
if (acceptedFrames <= 5 || acceptedFrames % 250L == 0L) {
Log.i(TAG, "Writing mixed PCM bytes=${frame.size} trackState=${activeTrack.state} playState=${activeTrack.playState}")
Log.i(TAG, "Writing mixed PCM bytes=${gainedFrame.size} gain=$receiveGain trackState=${activeTrack.state}")
}
val written = activeTrack.write(frame, 0, frame.size, AudioTrack.WRITE_BLOCKING)
val written = activeTrack.write(gainedFrame, 0, gainedFrame.size, AudioTrack.WRITE_BLOCKING)
if (written != frame.size) {
trackWriteFailures++
Log.w(TAG, "AudioTrack.write incomplete: $written/${frame.size}")
@@ -341,4 +349,21 @@ class VoiceService(
selfSpeakingJob?.cancel(); selfSpeakingJob = null
Log.d(TAG, "VoiceService destroyed")
}
/**
* 对 PCM16 字节数组应用增益,clamp 到 int16 范围防止溢出。
* PCM 格式:小端序 interleaved stereo。
*/
private fun applyPcmGain(pcm: ByteArray, gain: Float): ByteArray {
if (gain == 1.0f) return pcm
val result = pcm.copyOf()
for (i in result.indices step 2) {
// 小端序:低字节在前
val sample = ((result[i + 1].toInt() shl 8) or (result[i].toInt() and 0xFF)).toShort()
val gained = (sample.toFloat() * gain).toInt().coerceIn(Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt())
result[i] = (gained and 0xFF).toByte()
result[i + 1] = (gained shr 8).toByte()
}
return result
}
}