Задержка AudioTrack: тайм-аут получения буфера

Я проигрываю WAV на своем телефоне Android, загружая файл и передавая байты в AudioTrack.write () через метод FileInputStream> BufferedInputStream> DataInputStream. Звук воспроизводится нормально, и когда это происходит, я могу легко настроить частоту дискретизации, громкость и т. Д. На лету с хорошей производительностью. Однако для начала воспроизведения трека требуется около двух полных секунд. Я знаю, что AudioTrack имеет неизбежную задержку, но это просто смешно. Каждый раз, когда я проигрываю трек, я получаю следующее:

03-13 14:55:57.100: WARN/AudioTrack(3454): obtainBuffer timed out (is the CPU pegged?) 0x2e9348 user=00000960,     server=00000000
03-13 14:55:57.340: WARN/AudioFlinger(72): write blocked for 233 msecs, 9 delayed writes, thread 0xba28

I ' Мы заметили, что счетчик отложенной записи увеличивается на единицу каждый раз, когда я проигрываю трек - даже во время нескольких сессий - с момента включения телефона. Время блока всегда составляет 230–240 мс, что имеет смысл с учетом минимального размера буфера 9600 на этом устройстве (9600/44100). Я видел это сообщение в бесчисленных поисках в Интернете, но обычно кажется, что оно связано с отсутствием воспроизведения звука или его пропуском. В моем случае это просто отложенный старт.

Я запускаю весь свой код в потоке с высоким приоритетом. Вот урезанная, но функциональная версия того, что я делаю. Это обратный вызов потока в моем классе воспроизведения. Опять же, это работает (сейчас воспроизводятся только 16-битные, 44,1 кГц, стерео файлы), для запуска требуется вечность, и каждый раз появляется сообщение getBuffer / delayed write.

public void run() {

    // Load file
    FileInputStream mFileInputStream;
    try {
        // mFile is instance of custom file class -- this is correct, 
        // so don't sweat this line
        mFileInputStream = new FileInputStream(mFile.path());
    } catch (FileNotFoundException e) {
        // log
    }

    BufferedInputStream mBufferedInputStream = new BufferedInputStream(mFileInputStream, mBufferLength);
    DataInputStream mDataInputStream = new DataInputStream(mBufferedInputStream);

    // Skip header
    try {
        if (mDataInputStream.available() > 44) {
            mDataInputStream.skipBytes(44);
        }
    } catch (IOException e) {
        // log
    }

    // Initialize device
    mAudioTrack = new AudioTrack(
        AudioManager.STREAM_MUSIC, 
        ConfigManager.SAMPLE_RATE, 
        AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
        AudioFormat.ENCODING_PCM_16BIT, 
        ConfigManager.AUDIO_BUFFER_LENGTH,
        AudioTrack.MODE_STREAM
    );
    mAudioTrack.play();

    // Initialize buffer
    byte[] mByteArray = new byte[mBufferLength];
    int mBytesToWrite = 0;
    int mBytesWritten = 0;

    // Loop to keep thread running
    while (mRun) {

        // This flag is turned on when the user presses "play"
        while (mPlaying) {

            try {
                // Check if data is available
                if (mDataInputStream.available() > 0) {

                    // Read data from file and write to audio device
                    mBytesToWrite = mDataInputStream.read(mByteArray, 0, mBufferLength);
                    mBytesWritten += mAudioTrack.write(mByteArray, 0, mBytesToWrite);

                }
            }
            catch (IOException e){
                // log
            }                
        }   
    }
}

Если мне удастся преодолеть искусственно долгую задержку, я могу легко справиться с задержкой при наследовании, начав запись с более поздней, предсказуемой позиции (т.е. пропустив минимальную длину буфера, когда я начинаю воспроизведение файла).

10
задан Airon Tark 17 December 2015 в 14:29
поделиться