Я не уверен насчет ужасного звука, который вы слышите близко, но я думаю, что у меня есть идея, как решить проблему перекрытия, о которой вы упомянули. Похоже, что вы используете Sound API нормально, но я подозреваю, что у вас может быть проблема с параллелизмом. Я заметил, что вы начинаете новую тему для каждого звука, который вы играете. Это хорошая идея, но вы должны быть осторожны, если не хотите, чтобы ваши песни смешивались. Моя теория заключается в том, что ваш код выглядит примерно так:
Music songA = new Music();
Music songB = new Music();
//Start playing song A
songA.playMusic("path");
//Some stuff happens with your game...
//Some time later you want to change to song B
songA.stop();
songB.playMusic("other path");
На первый взгляд все выглядит хорошо, в конце концов, вы были осторожны, чтобы остановить songA перед запуском songB, верно? К сожалению, когда дело доходит до параллелизма, некоторые вещи настолько просты, насколько нам этого хотелось бы. Давайте рассмотрим небольшой кусочек вашего кода, в частности цикл while
, отвечающий за подачу данных в аудиопоток ...
//Inside run(), this is the interesting bit at the end
while(nBytesRead != -1 && play == true){
//Feed the audio stream while there is still data
}
stop()
устанавливает play
в значение false, вызывая выход из цикла while, после завершения текущей итерации . Если я не ошибаюсь, каждая итерация вашего цикла while
отправляет 64k данных в аудиопоток. 64k - это достаточное количество аудиоданных, и в зависимости от свойств звука будет продолжаться в течение некоторого времени. То, что вы действительно хотите сделать, это сообщить потоку о выходе (то есть установить play в false), и затем ждать завершения потока . Я полагаю, что это решит проблему перекрытия, и если вы не убиваете свои потоки должным образом, эта проблема может также вызвать ужасную ракетку при выходе. Я смиренно предлагаю следующее изменение в вашем музыкальном классе (без гарантии правильности) ...
public class Music implements Runnable{
private Thread t; //Make the thread object a class field
//Just about everything is the same as it was before...
public void stop(){
play = false;
try{
t.join()
}catch(InterruptedException e){
//Don't do anything, it doesn't matter
}
}
}
Надеюсь, это поможет, и ради любви ко всему хорошему и чистому, не используйте мой код как есть, он сошел с моей головы примерно через 2 минуты. Я рекомендую Серия Java Tutorials по многопоточности .