AudioTrack: воспроизведение звука через WiFi - PullRequest
10 голосов
/ 14 марта 2011

В моем приложении есть AudioTrack, который настроен на потоковый режим. Я хочу написать аудио, которое я получаю через беспроводное соединение. AudioTrack объявлен так:

mPlayer = new AudioTrack(STREAM_TYPE,
                         FREQUENCY,
                         CHANNEL_CONFIG_OUT,
                         AUDIO_ENCODING,
                         PLAYER_CAPACITY,
                         PLAY_MODE);

Где параметры определены как:

private static final int FREQUENCY = 8000,
                         CHANNEL_CONFIG_OUT = AudioFormat.CHANNEL_OUT_MONO,
                         AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT,
                         PLAYER_CAPACITY = 2048,
                         STREAM_TYPE = AudioManager.STREAM_MUSIC,
                         PLAY_MODE = AudioTrack.MODE_STREAM;

Однако, когда я записываю данные в AudioTrack с помощью write (), он воспроизводится прерывисто ... Вызов

byte[] audio = packet.getData();
mPlayer.write(audio, 0, audio.length);

создается при получении пакета по сетевому соединению. У кого-нибудь есть идея, почему это звучит нестабильно? Может быть, это как-то связано с самим WiFi-соединением? Я так не думаю, поскольку звук не звучит ужасно, когда я посылаю данные с телефона Android в другой источник по UDP. Звук тогда звучит законченным и совсем не прерывистым ... Так кто-нибудь имеет представление о том, почему это происходит?

Ответы [ 2 ]

7 голосов
/ 14 марта 2011

Знаете ли вы, сколько байтов в секунду вы получаете, сравнивает среднее время между пакетами и максимальное время между пакетами?Если нет, можете ли вы добавить код для его расчета?

Вам необходимо усреднить 8000 выборок / секунду * 2 байта / выборка = 16 000 байтов в секунду , чтобы сохранить поток заполненным.

Пробел более2048 байт / (16000 байт / с) = 128 миллисекунд между входящими пакетами приведут к тому, что ваш поток иссякнет и звук заикается.

Один из способов предотвратить это - увеличить размер буфера (PLAYER_CAPACITY).Больший буфер будет более способен обрабатывать изменения в размере и скорости входящего пакета.Стоимость дополнительной стабильности - большая задержка при запуске воспроизведения, пока вы ожидаете первоначального заполнения буфера.

5 голосов
/ 14 марта 2011

Я частично решил это, поместив mPlayer.write(audio, 0, audio.length); в его собственное Thread.Это устраняет некоторую нестабильность (из-за того, что запись является блокирующим вызовом), но по-прежнему звучит прерывисто после хорошей секунды или 2. У него все еще значительная задержка 2-3 секунды.

new Thread(){
    public void run(){
        byte[] audio = packet.getData();
        mPlayer.write(audio, 0, audio.length);
    }
}.start();

Просто маленький аноним Thread, который пишет сейчас ...

У кого-нибудь есть идеи, как решить эту проблему?


Редактировать:

После некоторых дополнительных проверок и отладки я заметил, что это проблема с receiveBuffer.Я посмотрел на код Java AudioTrack и C ++ код AudioTrack И заметил, что он может появиться только в коде C ++.

if (__builtin_expect(result!=NO_ERROR, false)) {
    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
            "user=%08x, server=%08x", u, s);
    mAudioTrack->start(); // FIXME: Wake up audioflinger
    timeout = 1;
}

Я заметил, что в этом фрагменте кода есть FIXME.: <Но в любом случае, кто-нибудь может объяснить, как работает этот код C ++?У меня был некоторый опыт работы с ним, но он никогда не был таким сложным, как этот ... </p>


Редактировать 2:

Я пробовал несколько иначе, разница в том, чтоЯ буферизирую данные, которые я получаю, и затем, когда буфер заполняется некоторыми данными, они записываются в проигрыватель.Тем не менее, игрок продолжает потреблять в течение нескольких циклов, затем срабатывает предупреждение obtainBuffer timed out (is the CPU pegged?), и игроку вообще ничего не записывается до тех пор, пока его удар не вернется к жизни ... После этого он будет постояннополучить данные, записанные в него, пока буфер не будет очищен.

Еще одно небольшое отличие состоит в том, что я сейчас направляю файл на проигрыватель.То есть, читая его порциями, записывая эти порции в буфер.Это имитирует получение пакетов по Wi-Fi ...

Я начинаю задумываться, не является ли это просто проблемой ОС, которая есть у Android, и это не то, что я могу решить самостоятельно ... Кто-нибудь получилесть какие-нибудь идеи по этому поводу?


Редактировать 3:

Я провел больше испытаний, но это мне больше не помогает.Этот тест показывает, что у меня возникает задержка только при первой попытке записи в AudioTrack.Это займет от 1 до 3 секунд.Я сделал это, используя следующий бит кода:

long beforeTime = Utilities.getCurrentTimeMillis(), afterTime = 0;
mPlayer.write(data, 0, data.length);
afterTime = Utilities.getCurrentTimeMillis();
Log.e("WriteToPlayerThread", "Writing a package took " + (afterTime - beforeTime) + " milliseconds");

Тем не менее, я получаю следующие результаты: Logcat Image http://img810.imageshack.us/img810/3453/logcatimage.png

Они показывают, что отставание изначально происходит в начале,после чего AudioTrack продолжает непрерывно получать данные ... Мне действительно нужно исправить это ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...