Использование буфера с Android AudioTrack

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


person William Seemann    schedule 11.12.2013    source источник
comment
Почему вы хотите знать: сколько осталось и сколько было использовано/сыграно??   -  person SweetWisher ツ    schedule 11.12.2013
comment
Чтобы уведомить пользователя о буферизации приложения и выполнить соответствующую логику.   -  person William Seemann    schedule 11.12.2013


Ответы (2)


AudioTrack.write() возвращает «количество записанных байтов» в виде целого числа, и вы указываете количество байтов в буфере при построении AudioTrack.

Поэтому, чтобы отслеживать, сколько места в буфере осталось, вы можете сохранить переменную-аккумулятор, чтобы знать, сколько всего байтов было записано, и устанавливать эту переменную в ноль всякий раз, когда вы вызываете AudioTrack.flush(). Однако в связанной документации говорится, что «типично использовать куски 1/2 от общего размера, чтобы разрешить двойную буферизацию», поэтому может быть достаточно просто просто вспомнить, написали ли вы ноль, один или два раза с момента вызова flush .

Чтобы узнать, какая часть буфера воспроизведена, используйте AudioTrack.getPlaybackHeadPosition() который возвращает количество воспроизведенных кадров текущего буфера (т.е. сбрасывается до нуля при остановке, сбросе или перезагрузке) со знаком 32- битовое целое, но интерпретируется как 32-битное целое число без знака. Все это на самом деле означает, что вы назначаете его int следующим образом.

int bufferPlaybackFrame = myAudioTrack.getPlaybackHeadPosition() & 0xFF;

Вы можете думать о фреймах как об эквивалентах сэмплов. т. е. вы можете определить из AudioFormat, используемого для создания AudioTrack, сколько битов (и, следовательно, байтов) используется для каждого семпла.

Наконец, если кому-то интересно, вы никогда не сможете сказать, сколько исходного файла или потока осталось для воспроизведения через этот объект (одна из причин заключается в том, что он предназначен для работы с постоянными потоками 24/7, без окончания) , поэтому, если вы хотите сделать расчет, как вы видите на некоторых веб-сайтах, воспроизводящих видео, которые приостанавливают поток до тех пор, пока не будет буферизовано достаточное количество идентификаторов, чтобы увидеть все видео с текущей скоростью загрузки, вам придется передать эту информацию каким-то другим способом.

person vowel-house-might    schedule 18.12.2013
comment
Спасибо, очень полезный ответ. - person William Seemann; 18.12.2013
comment
@ Эндрю, что, если я хочу загрузить (один раз) аудиофайлы с сервера, а затем файлы должны воспроизводиться в автономном режиме. ? - person Devendra Singh; 11.07.2015
comment
@DevendraSingh, тогда вы бы использовали другой класс и метод вместе (у меня нет интуиции относительно того, какой именно). Это для доступа к постоянным, бесконечным, круглосуточным потокам, которые вы не можете загрузить и воспроизвести в автономном режиме. - person vowel-house-might; 12.07.2015
comment
Я не думаю, что кадры эквивалентны образцам. Кадры эквивалентны количеству сэмплов, если выход моно. Если это стерео, количество сэмплов в два раза превышает количество кадров, потому что каждый кадр будет одним сэмплом для левого канала и одним сэмплом для правого канала. - person Stéphane; 20.06.2019

*Этот код поможет воспроизводить аудио с буфером*

  private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException
    {

    // We keep temporarily filePath globally as we have only two sample sounds now..

    if (filePath==null)                                                                     
    return;

    //Reading the file..

    byte[] byteData = null; 
    File file = null; 
    file = new File(filePath); 

    // for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"

    byteData = new byte[(int) file.length()];
    FileInputStream in = null;
     try {
    in = new FileInputStream( file );
     in.read( byteData );
     in.close(); 
    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // Set and push to audio track..

    int intSize = android.media.AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
    AudioFormat.ENCODING_PCM_8BIT); 
    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
    AudioFormat.ENCODING_PCM_8BIT, intSize, AudioTrack.MODE_STREAM); 
    if (at!=null) { 
    at.play();

    // Write the byte array to the track

at.write(byteData, 0, byteData.length); 
    at.stop();
    at.release();
    }
    else
     Log.d("TCAudio", "audio track is not initialised ");
     }
person Asha Babu    schedule 16.12.2013
comment
Извините, я должен был быть более конкретным. У меня нет доступа ко всему файлу, потому что я транслирую его, поэтому я не могу загрузить весь файл в буфер перед воспроизведением. - person William Seemann; 17.12.2013