Несоответствия частоты дискретизации AudioTrack

Используя AudioTrack для воспроизведения, мне иногда нужно пересчитывать звук, который не соответствует частоте дискретизации, поддерживаемой AudioTrack. При этом мне нужно определить максимальную частоту дискретизации, поддерживаемую AudioTrack, под текущим устройством, при текущей аудио конфигурации.

Из-за того, что допустимые частоты дискретизации для AudioTrack плохо документированы, я решил поискать исходный код для AudioTrack и нашел эту ошеломляющую строку:

private static final int SAMPLE_RATE_HZ_MAX = 96000;

казалось бы, что AudioTrack Например, применяется жесткий предел в 96 кГц независимо от реальных возможностей воспроизведения устройства.

Более запутанным является AudioFormat класс, в котором я перехожу к конструктору (API 21) AudioTrack, который содержит эту строку:

if ((sampleRate <= 0) || (sampleRate > 192000)) {

в это setSampleRate() метод. Теперь это жесткий предел 192 кГц. Таким образом, передача> 192 кГц в AudioFormat (или его сборщик) приведет к IllegalArgumentException от AudioFormat и передача сконфигурированной AudioFormat частоты дискретизации 192 кГц IllegalArgumentException,


На мой взгляд, наиболее запутанным является метод getNativeOutputSampleRate() в AudioTrack, который на самом деле возвращает правильную частоту дискретизации на выходе (ну, не сильно удивительно, учитывая, что он запускается прямо из нативного слоя, но так непоследователен).

И в довершение всего, метод setPlaybackRate() который утверждает:

Допустимый диапазон частоты дискретизации составляет от 1 Гц до удвоенного значения, возвращаемого 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 кГц, код распечатывается:

Собственная скорость потока: 48000 Гц
Трек создан успешно (прямой)

но когда я подключаю внешний ЦАП с возможностями воспроизведения до 192 кГц, я получаю:

Собственная скорость потока: 192000 Гц
Не удалось создать AudioTrack с обычной скоростью!
Трек создан успешно (непрямой)

Что с этими несоответствиями? И является, setPlaybackRate() идентична частота дискретизации, переданная в конструктор?

1 ответ

В настоящее время большинство телефонов Android на рынке поддерживают только одну частоту дискретизации. Я считаю, что некоторые Samsungs играют на частоте 48 кГц, а почти все остальные - на частоте 44,1 кГц. Эти значения определяются аппаратным обеспечением, и хотя есть возможность изменить собственную частоту, его функция заключается во вторичной проверке на будущее, но прежде всего в 2. повторной выборке ВСЕГО звука во время выполнения в ПРОГРАММНОМ ОБЕСПЕЧЕНИИ. Это дорогостоящая задача, а также несколько разрушительная. Причина, по которой существует жесткое ограничение на 192 кГц (= 2 * 96 кГц), заключается в том, что отправка более чем в два раза максимальной частоты (96 кГц) является огромной тратой ресурсов, поскольку вы можете просто выбросить каждую вторую выборку, чтобы эффективно уменьшить частоту до в 2 раза, пока вы не окажетесь в этом диапазоне.

Указание ненативной частоты дискретизации лучше избегать. Он будет пересчитан в программном обеспечении и, в лучшем случае, является пустой тратой ресурсов, а в худшем - источником отставания.

Или услышать это от инженера Google

Другие вопросы по тегам