使用AudioTrack进行播放时,有时需要重新采样不符合AudioTrack支持的采样率的音频。在这样做时,我需要确定当前设备下当前音频配置下AudioTrack支持的最大采样率。
由于AudioTrack允许的采样率文档记录不够完整,因此我决定查看AudioTrack
源代码,并发现了这一惊人的代码行:
private static final int SAMPLE_RATE_HZ_MAX = 96000;
似乎“AudioTrack”实例正在应用一个96 KHz的硬限制,而不考虑设备的实际播放能力。
更令人困惑的是,在“AudioFormat”类中,我传递给“AudioTrack”的构造函数(API 21)的内容中包含这行代码:if ((sampleRate <= 0) || (sampleRate > 192000)) {
在setSampleRate()
方法中,设定了最高的采样率为192 KHz。因此,试图将大于192 KHz的采样率传递给AudioFormat(或其构建器)将导致AudioFormat
抛出IllegalArgumentException
异常,而将配置为192 KHz<x<96 KHz采样率的AudioFormat传递到AudioTrack也会抛出IllegalArgumentException
异常。
至今为止,我发现最令人困惑的是AudioTrack中的getNativeOutputSampleRate()
方法,它实际上返回正确的输出采样率(出于直接从本地层运行的原因,并不令人惊讶,但仍然非常不一致)。
为了更完整地说明这个问题,让我们来看一下声称:
有效的采样率范围从1 Hz到由
getNativeOutputSampleRate(int)
返回值的两倍。
实际上,我尝试了一下,它确实可行?请考虑以下代码片段:
int nativeRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
android.util.Log.i("UI", "Native stream rate: " + nativeRate + " Hz");
// Build audio attributes
AudioAttributes.Builder attribBuilder = new AudioAttributes.Builder();
attribBuilder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC);
attribBuilder.setUsage(AudioAttributes.USAGE_MEDIA);
AudioAttributes attrib = attribBuilder.build();
// Build audio format
AudioFormat.Builder afBuilder = new AudioFormat.Builder();
afBuilder.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO);
afBuilder.setEncoding(AudioFormat.ENCODING_PCM_16BIT);
afBuilder.setSampleRate(nativeRate);
try{
AudioTrack trackTest = new AudioTrack(attrib, afBuilder.build(), nativeRate, AudioTrack.MODE_STREAM, 0);
android.util.Log.i("UI", "Track created successfully (direct)");
}catch(Exception ex){
android.util.Log.w("UI", "Failed to create AudioTrack at native rate!");
// Use a random supported samplerate to get pass constructor
afBuilder.setSampleRate(48000);
try{
AudioTrack trackTest = new AudioTrack(attrib, afBuilder.build(), nativeRate, AudioTrack.MODE_STREAM, 0);
trackTest.setPlaybackRate(nativeRate);
android.util.Log.i("UI", "Track created successfully (indirect)");
}catch(Exception e){
android.util.Log.w("UI", "Failed to create AudioTrack at 48 KHz");
}
}
根据程序流程,当本地采样率< 96 KHz时,代码会打印出:
本机流速率:48000 Hz
轨道创建成功(直接)
但是,当我连接一个支持最高播放速度为192 KHz的外部DAC时,输出为:
本机流速率:192000 Hz
无法以本机速率创建AudioTrack!
轨道创建成功(间接)
这些差异是什么原因?而且,setPlaybackRate()
是否与传递到构造函数中的采样率相同?