Hörgeschichte lag: obtainBuffer timed out
Spielte ich die WAVs auf meinem Android-Handy durch laden der Datei und die Fütterung der bytes in Hörgeschichte.schreiben() über den FileInputStream > BufferedInputStream > DataInputStream-Methode. Das audio spielt fein und wenn es soweit ist, kann ich leicht anpassen, sample-rate, Volumen, etc. on-the-fly mit schön Leistung. Jedoch, es dauert etwa zwei volle Sekunden für einen track zum starten der Wiedergabe. Ich weiß Hörgeschichte hat eine unausweichliche Verzögerung, aber das ist lächerlich. Jedes mal, wenn ich einen Titel abzuspielen, bekomme ich diese:
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
Ich habe bemerkt, dass die delayed write Zähler um eins erhöht jedes mal, wenn ich einen Titel Abspielen-auch über mehrere Sitzungen hinweg -- von der Zeit, die das Telefon eingeschaltet wurde. Die block-Zeit ist immer 230 - 240ms, was Sinn macht, angesichts einer minimalen Puffergröße von 9600 auf das Gerät (9600 /44100). Ich habe gesehen, diese Nachricht in unzähligen Recherchen im Internet, aber in der Regel scheint verknüpft werden, um nicht die audio-Wiedergabe oder überspringen von audio. In meinem Fall ist es nur ein verzögerter start.
Ich bin mit allen meinen code in eine hohe Priorität thread. Hier ist ein abgeschnitten-noch-funktionale version von dem, was ich Tue. Dies ist die callback-thread in meiner Wiedergabe-Klasse. Wieder, das funktioniert (die spielen nur 16-bit, 44.1 kHz, stereo Dateien jetzt), es braucht nur ewig zum starten und ist, dass obtainBuffer/verzögerte Nachricht schreiben jedes mal.
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
}
}
}
}
Wenn ich kann, vorbei an der künstlich lange lag, kann ich leicht befassen sich mit den Erben Latenz von ab mein schreiben zu einem späteren, vorhersehbaren position (ie, überspringen Sie die minimale Puffergröße, wenn ich starten Sie die Wiedergabe einer Datei).
- Ich habe ein ähnliches problem im moment. Hast du eine Lösung?
- noch nicht, leider. :/
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich lief in ein ähnliches problem, obwohl ich mit einem RandomAccessFile, statt einen BufferedInputStream zu Lesen der PCM-Daten. Das Problem war, dass die Datei-I/O-war zu langsam. Ich vermute, Sie haben dieses problem, auch mit einem gepufferten stream, da die I/O ist immer noch der gleiche thread wie audio-Verarbeitung.
Die Lösung ist, zwei threads: Ein thread, der die Puffer liest aus einer Datei und speichert Sie in den Speicher, und ein anderer thread liest, die von dieser Warteschlange ab und schreibt die audio-hardware. Habe ich eine ConcurrentLinkedQueue, dies zu erreichen.
Ich die gleiche Technik für die Aufzeichnung, mit AudioRecord, aber in umgekehrter Richtung. Der Schlüssel ist, um die Datei-I/O auf einem separaten thread.
Ein bisschen spät, um die Partei zu beantworten, aber falls es hilft jemand in der Zukunft - ich lief in dieses genaue problem mit code ziemlich ähnlich wie der code in der Frage, wo die Hörgeschichte ist erstellt und zu spielen, aber nicht sofort.
Fand ich, dass die Erstellung der Tonspur besitzt, unmittelbar bevor Sie anfangen zu schreiben, um es aus der delay Weg. Aus irgendeinem Grund Hörgeschichte scheint nicht, wie sitzen, um mit einem leeren Puffer.
In Bezug auf den code oben, würden Sie wollen, etwas zu tun, wie