Android Kotlin:使用ToneGenerator播放特定频率提示音遇阻
问题解答
核心结论
ToneGenerator 不支持播放任意自定义频率,它的startTone方法仅用于播放系统预定义的固定音调(比如DTMF按键音、标准提示音),没有参数允许直接传入自定义频率值。你代码里的第三个参数确实在新版Android SDK中已被移除,而且这个参数原本也不是用来设置频率的,属于之前的误解。
替代方案:用AudioTrack实现自定义频率播放
如果需要播放任意频率的提示音,建议使用AudioTrack类,通过生成对应频率的正弦波数据来实现。你可以复用同一个AudioTrack实例来切换不同频率,无需每次创建新对象。
示例代码如下:
import android.media.AudioFormat import android.media.AudioManager import android.media.AudioTrack class CustomTonePlayer { private val sampleRate = 44100 // 标准音频采样率 private var audioTrack: AudioTrack? = null init { // 初始化AudioTrack实例 val bufferSize = AudioTrack.getMinBufferSize( sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT ) audioTrack = AudioTrack( AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM ) } fun playTone(frequency: Float, durationMs: Int = 1000) { audioTrack?.let { track -> if (track.state != AudioTrack.STATE_INITIALIZED) return val numSamples = (sampleRate * durationMs / 1000).toInt() val samples = ShortArray(numSamples) val amplitude = 0.5 * Short.MAX_VALUE // 控制音量大小 // 生成对应频率的正弦波数据 for (i in 0 until numSamples) { val angle = 2 * Math.PI * frequency * i / sampleRate samples[i] = (amplitude * Math.sin(angle)).toShort() } // 开始播放 if (track.playState != AudioTrack.PLAYSTATE_PLAYING) { track.play() } track.write(samples, 0, numSamples) } } // 释放资源,避免内存泄漏 fun release() { audioTrack?.stop() audioTrack?.release() audioTrack = null } }
使用说明
- 调用
playTone(200)即可播放200Hz的声音,默认持续1秒,可通过第二个参数调整时长 - 应用退出或不再需要播放时,务必调用
release()释放AudioTrack资源
内容的提问来源于stack exchange,提问作者Pranav Subramanian
相关产品推荐
相关产品推荐

