Замедление таймера метронома (через обработчик или потоки тоже)

У меня есть простое классическое утверждение, что каждые 200 миллисекунд воспроизводится звук (метроном).

Я написал это с помощью Handlers, а потом по-другому, с помощью Threads. Проблема одинакова в обоих случаях: когда я нажимаю аппаратную кнопку домой, а также просто когда я нажимаю кнопку, чтобы открыть ListView, метроном ужасно тормозит на некоторое время.

Эта проблема (не такая сильная, но, тем не менее, присутствующая) заключается в том, что вы ничего не делаете и оставляете приложение на переднем плане.

Любые идеи?

Вот код:

общедоступный класс Metronome реализует 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);
   }

};


person Geltrude    schedule 27.10.2010    source источник
comment
Это проблема с точными таймингами на подобных устройствах. Не уверен, что есть решение вообще, не говоря уже о простом   -  person Falmarri    schedule 27.10.2010


Ответы (3)


Вы используете какой-то оператор паузы, чтобы ждать между ударами? Вместо этого вы можете попробовать использовать время, кратное значению системных часов. Таким образом, вы все еще можете получать такты, которые появляются поздно (или не появляются вовсе), но вы не получаете замедления. Надеюсь, это имеет какой-то смысл.

Это скорее комментарий, но у меня пока недостаточно представителей, чтобы оставлять комментарии.

person learnvst    schedule 27.10.2010

Кажется, мой телефон может воспроизводить миди-файлы, которые представляют собой довольно компактный способ представления звука, возможно, вы могли бы динамически создать его и использовать для метронома? Я предполагаю, что синтез обрабатывается на более низком уровне, чем тот, который обычно доступен для вас, так что время будет лучше, но я не уверен в этом на самом деле.

person Chris Stratton    schedule 27.10.2010
comment
Аналогичная идея: генерировать звуковой поток, в котором звук метронома следует за тишиной, а не воспроизводить звук и останавливаться. До тех пор, пока ваш поток получает достаточно процессорного времени для заполнения звукового буфера, ваш метроном будет работать вовремя, даже если другие элементы в системе активны. - person fadden; 28.10.2010

Когда этот звук воспроизведения называется

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);
person activedecay    schedule 07.01.2016