Замедление таймера метронома (с помощью обработчика или потоков)
У меня есть простое, классическое утверждение, что каждые 200 миллисекунд воспроизводится звук (метроном).
Я написал это с помощью обработчиков, а затем по-другому, используя потоки. Проблема одинакова в обоих случаях: когда я нажимаю аппаратную кнопку "домой" или просто когда я нажимаю кнопку, чтобы открыть ListView, метроном на какое-то время ужасно замедляется.
Эта проблема (не такая сильная, но, тем не менее, присутствует) представляет также отсутствие действий и оставление приложения на переднем плане.
Есть идеи?
Вот код:
открытый класс Метроном реализует Runnable {
private Handler mHandler = new Handler();
public static long mStartTime;
Main mainContext;
public Metronomo(Main context) {
mainContext = context;
}
public void play() {
mStartTime = System.currentTimeMillis();
mHandler.postDelayed(this, 100);
}
public final void stop(){
mHandler.removeCallbacks(this);
}
public void run(){
//play the ogg file in position 1
mSoundManager.playSound(1);
//reschedule the next playing after 200ms
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
}
};
3 ответа
Кажется, мой телефон может воспроизводить миди-файлы, которые представляют собой довольно компактный способ представления звука, возможно, вы могли бы динамически создать его и использовать его для метронома? Я предполагаю, что синтез обрабатывается на более низком уровне, чем обычно был бы доступен для вас, так что время было бы лучше, но я не знаю это на самом деле.
Используете ли вы какой-то оператор паузы для ожидания между ударами? Вместо этого вы можете попытаться основать время на кратных системного значения. Таким образом, вы все равно можете получить удары, которые происходят поздно (или не совсем), но вы не получите замедления. Надеюсь, это имеет какой-то смысл.
Это скорее комментарий, но у меня пока недостаточно представителей, чтобы оставлять комментарии.
Когда этот звук воспроизведения называется
mSoundManager.playSound(1);
Android ждет, пока этот вызов не закончится, затем вы звоните
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
однако, если вы отмените эти вызовы, вы можете обнаружить, что время более точное.
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
mSoundManager.playSound(1);
Вы не можете рассчитывать на то, что ваш звук занимает ровно столько же времени для воспроизведения, поэтому лучше сказать обработчику публиковать сообщение первым. Все еще не идеал, как бы то ни было.
Другое соображение заключается в том, что вы пересчитываете время безотказной работы и добавляете к этому еще немного времени (в нашем случае 200). Почему бы не использовать оператор модуля в вашем рабочем времени, чтобы гарантировать, что ваше следующее запрошенное время поста будет более точно запланировано?
long divisions = SystemClock.uptimeMillis() % 200; // precisely scheduled event timings since system boot.
long nextDivision = divisions + 1; // the next desired event timing
mHandler.postAtTime(this, nextDivision * 200); // scaled back up to number of milli seconds
// now do more heavy lifting that would otherwise have affected uptimeMillis call
mSoundManager.playSound(1);