使用AudioTrack进行播放时,我有时需要对不符合AudioPrack支持的采样率的音频进行重新采样。在这样做的过程中,我需要确定AudioTrack在当前设备和当前音频配置下支持的最大采样率。
由于AudioTrack的允许采样率记录不足,我决定窥探AudioTrack
的源代码,发现了这条令人震惊的线:
private static final int SAMPLE_RATE_HZ_MAX = 96000;
看起来CCD_ 2实例正在应用96KHz的硬限制,而与设备的实际回放能力无关。
更令人困惑的是AudioFormat
类,其中我传递给AudioTrack
的构造函数(API 21),其中包含以下行:
if ((sampleRate <= 0) || (sampleRate > 192000)) {
在CCD_ 5方法中。现在这是一个192 KHz的硬限制。因此,将>192KHz传递到AudioFormat(或其构建器)将导致AudioFormat
中的IllegalArgumentException
,并将配置的192KHz<x<96 KHz采样率AudioFormat转换为AudioTrack也将抛出IllegalArgumentException
。
到目前为止,我发现最令人困惑的是AudioTrack中的方法getNativeOutputSampleRate()
,它实际上返回了正确的输出采样率(好吧,这并不奇怪,因为它是直接从原生层运行的,但非常不一致)。
最重要的是,方法setPlaybackRate()
声称:
有效的采样率范围从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()
与传递到构造函数的采样率相同吗?
目前市场上大多数安卓手机只支持一种采样率。我相信某些三星以48kHz的频率播放,几乎所有其他三星以44.1kHz的频率播放。这些值是由硬件决定的,尽管有更改本地速率的功能,但它的功能是次要的,但主要是2。在软件运行时对所有音频重新采样。这是一项昂贵的任务,也有一定的破坏性。192kHz(=2*96kHz)有一个硬限制的原因可能是,发送超过最大频率(96kHz)两倍的频率是对资源的巨大浪费,因为你还可以丢弃每一秒的样本,以有效地将样本减少2倍,直到达到这个范围。
最好避免指定非本地采样率。它将在软件中重新采样,往好了说是浪费资源,往坏了说是滞后的来源。
或者从谷歌工程师那里听到