Я думаю, что это общий вопрос Java, но он затрагивает некоторые аспекты Android.
Итак, вот в чем дело: у меня есть версия MPG123 для Android в JNI-оболочке, и я могу получать данные PCMиз файла MP3 на SDCard.Я хотел бы выделить эти данные, проанализировать их с помощью другого класса, который я написал, а затем поместить их в очередь.В идеале я хотел бы, чтобы звук воспроизводился с задержкой в четыре секунды.Я добился этого без задержки, используя этот код:
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?Может быть, это какая-то странная ошибка с AndroidTrack Audio?
Спасибо!
-Гриф
РЕДАКТИРОВАТЬ - Я решил проблему.Кажется, это проблема с моей реализацией JNI в GetPCM.Похоже, что когда я копировал данные в PCM с уровня JNI, он устанавливал одни и те же данные для каждого экземпляра 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;
}