有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java 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(或其构建器)将导致IllegalArgumentExceptionAudioFormat传递配置的192 KHz<;x<;96 KHz采样率AudioFormat转换为AudioTrack也会抛出一个IllegalArgumentException


到目前为止,我发现最令人困惑的是AudioTrack中的方法getNativeOutputSampleRate(),它实际上返回了正确的输出采样率(好吧,这并不奇怪,因为它直接从本机层运行,但不一致)

最重要的是,方法setPlaybackRate()声称:

The valid sample rate range is from 1 Hz to twice the value returned by getNativeOutputSampleRate(int).

事实上,我确实试过了,效果如何?考虑下面的片段:

int nativeRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);

安卓.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);

    安卓.util.Log.i("UI", "Track created successfully (direct)");
}catch(Exception ex){
    安卓.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);

        安卓.util.Log.i("UI", "Track created successfully (indirect)");
    }catch(Exception e){
        安卓.util.Log.w("UI", "Failed to create AudioTrack at 48 KHz");
    }
}

遵循程序流,当本机采样率时<;96 KHz,代码打印出来:

Native stream rate: 48000 Hz
Track created successfully (direct)

但是,当我连接一个播放能力高达192 KHz的外部DAC时,我得到:

Native stream rate: 192000 Hz
Failed to create AudioTrack at native rate!
Track created successfully (indirect)

这些不一致是怎么回事?并且,setPlaybackRate()与传递给构造函数的采样率相同吗


共 (1) 个答案

  1. # 1 楼答案

    目前市场上大多数Android手机只支持一个采样率。我相信某些三星的频率是48kHz,而几乎所有其他三星的频率都是44.1kHz。这些值由硬件决定,虽然有一个工具可以更改本机速率,但它的功能是将本机速率从第二级更改为将来的证明,但主要是更改为2。在软件运行时重新采样所有音频。这是一项昂贵的任务,也有一定的破坏性。192kHz(=2*96kHz)有一个硬限制的原因可能是因为发送两倍以上的最大频率(96kHz)是一种巨大的资源浪费,因为您可能只需扔掉每一秒的样本,以有效地将样本减少2倍,直到您处于该范围内

    最好避免指定非本机采样率。它将在软件中重新采样,充其量是对资源的浪费,充其量是滞后的根源

    Or hear it from a Google engineer