我認爲這是一個普通的Java問題,但它涉及到一些Android的東西。Java隊列,數組和JNI
因此,這裏的協議:我有一個JNI包裝的MPG123 for Android版本,我可以從SD卡上的MP3文件中提取PCM數據。我想將這些數據大塊,使用我寫的另一個類對其進行分析,然後將其推入隊列。理想情況下,我希望音頻以4秒的延遲播放。我使用此代碼沒有延遲實現它:
public void run()
{
// The actual thread where the PCM data gets processed and analyzed
short[] pcm = new short[ 4096 ];
short[] zero = new short[ 4096 ];
Queue<short[]> buffer = new LinkedList<short[]>();
// Fill the zero buffer
for(int i = 0; i < 4096; i++)
zero[i] = 0;
// Push back 4 seconds of silence - Note this commented section
//for(int i = 0; i < 43; i++)
// buffer.add(zero);
// Analyze the whole file
while(!isInterrupted())
{
// Grab and analyze data, add events
int ret = audio.GetPCM(pcm);
//Log.d("AudioThread", "GetPCM returns: " + ret);
if(ret != MPG123.MPG123_DONE)
{
// Process the PCM data
if(bd.Process(pcm) != BeatDetection.AUDALYSIS_OK)
Log.v("AudioThread", "Beat Detection Error!");
// Add the data to the PCM buffer
buffer.add(pcm);
}
// Play the audio
short[] data = buffer.poll();
if(data != null) // If we have data left in the buffer
at.write(data, 0, 4096); // Write it to the audio track
else
break; // Otherwise we need to exit the loop
Log.d("AudioThread", "BufferSize= " + buffer.size());
}
// Debug message
Log.d("AudioThread", "Exiting Thread.");
// Clean stuff up
bd.Cleanup();
audio.Cleanup();
at.stop();
at.release();
}
這就是說,當我嘗試通過添加「4秒。」 0的值到隊列(注的註釋塊)推出延遲到我的隊列,我的音樂立即播放,但是會在歌曲開始4秒後實時播放,直到隊列開始清空,它會一遍又一遍地播放相同的音塊,直到跳出循環。它看起來好像是隊列的行爲像「先進先出」隊列,而不是「先入先出」隊列。
也許我沒有正確使用Java隊列?也許這是Android AudioTrack的一些奇怪的錯誤?
謝謝!
-Griff
編輯 - 我解決了這個問題。這似乎是我的JNI實施GetPCM的一個問題。看起來,當我將數據從JNI級別複製到PCM中時,它爲每個推回到隊列中的PCM實例設置相同的數據,將隊列中的每個PCM條目設置爲PCM數據的相同幀。
buffer.add(pcm);
到
buffer.add(pcm.clone());
新問題:我通過改變解決了這個問題 這是正常的Java行爲?我是否錯誤地實現了JNI功能?
JNIEXPORT jint JNICALL Java_com_motalenbubble_projectlucid_MPG123_GetPCM(
JNIEnv* env,
jobject obj,
jshortArray data) // jshortarray already has a size attribute
{
// Call mpg123_read
jint err = MPG123_OK, length;
jshort *pcm;
jsize len = (*env)->GetArrayLength(env, data);
pcm = (*env)->GetShortArrayElements(env, data, NULL);
err = mpg123_read(mh, (unsigned char*)pcm, len * sizeof(short), &length); // Read length is in bytes - we need in shorts.
(*env)->ReleaseShortArrayElements(env, data, pcm, 0);
// Annoying logging
//dprintf(0, "read(%d): %s\n", length, err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err));
return err;
}
嗨格里芬,你可以請分享jni包裝版的MPG123爲Android? ----謝謝,Swathi – 2011-01-24 11:14:20
當然。我可以發送你的方式。給我發電子郵件 - griffyboy0 - at - gmail – Griffin 2011-01-29 20:56:27