Я играю 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
Я заметил, что отсроченная запись увеличивается на единицу каждый раз, когда я играю трек - даже за несколько сеансов - с моментателефон был включен.Время блока всегда 230-240 мс, что имеет смысл, учитывая минимальный размер буфера 9600 на этом устройстве (9600/44100).Я видел это сообщение в бесчисленных поисках в интернете, но обычно оно связано с тем, что оно вообще не воспроизводит звук или пропускает звук.В моем случае это просто отложенный запуск.
Я выполняю весь мой код в потоке с высоким приоритетом.Вот усеченная, но функциональная версия того, что я делаю.Это обратный вызов потока в моем классе воспроизведения.Опять же, это работает (сейчас воспроизводятся только 16-битные, 44,1 кГц, стереофайлы), для запуска требуется вечность, и каждый раз появляется сообщение о получении буфера / отложенной записи.
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
}
}
}
}
Если я могу получитьпосле искусственно длинной задержки я легко справлюсь с задержкой наследования, начав запись с более предсказуемой позиции (т. е. пропустив минимальную длину буфера при начале воспроизведения файла).