节拍器计时器减慢(通过处理程序或线程)

发布于 2024-09-29 04:59:54 字数 861 浏览 0 评论 0原文

我有一个简单、经典的说法,即每 200 毫秒播放一次声音(节拍器)。

我使用处理程序编写它,然后以另一种方式使用线程编写它。 两种方式的问题都是相同的:当我按下硬件主页按钮时,或者只是当我按下按钮打开 ListView 时,节拍器会严重减慢一段时间。

这个问题(不是那么严重,但仍然存在)也表现为不执行任何操作并将应用程序留在前台。

有什么想法吗?

代码如下:

public class Metronome Implements 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);
   }

};

I have a simple, classic, statement that every 200 milliseconds plays a sound (a metronome).

I wrote it using Handlers, and then in another way, using Threads.
The problem is the same in both ways: when I press hardware home button, or also simply when I press a button to open a ListView, the metronome terribly slowdown for a while.

This problem (not so strong, but however present) presents also doing nothing and leaving the application in foreground.

Any ideas?

Here's the code:

public class Metronome implements 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);
   }

};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

机场等船 2024-10-06 04:59:54

您是否使用某种暂停语句在节拍之间等待?您可以尝试将计时基于系统时钟值的倍数。这样,您可能仍然会得到较晚出现(或根本不出现)的节拍,但不会减慢速度。希望这有某种意义。

这更像是一条评论,但我还没有足够的代表来发表评论。

Are you using some kind of pause statement to wait between beats? You could try basing the timing on multiples of a system clock value instead. That way you may still get beats that occur late (or not at all) but you wouldn't get a slow down. Hope that makes some kind of sense.

This is more of a comment but I don't have enough rep to leave comments just yet.

べ映画 2024-10-06 04:59:54

我的手机似乎能够播放 midi 文件,这是一种非常紧凑的声音表示方式,也许您可​​以动态创建一个文件并将其用于节拍器?我假设合成的处理级别比您通常可以访问的级别要低,这样时机会更好,但事实上我不知道这一点。

My phone seems to be able to play midi files, which are a pretty compact way to represent sound, perhaps you could dynamically create one and use that for the metronome? I'm assuming that the synthesis is handled at a lower level than would ordinarily be accessible to you so that the timing would be better, but I don't know that for a fact.

纵山崖 2024-10-06 04:59:54

当这个播放声音被调用时,

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);

When this play sound is called

mSoundManager.playSound(1);

Android waits until that call is finished, then you call

mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);

however, if you reverse those calls, you may find that the timing is more accurate.

mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
mSoundManager.playSound(1);

You can't count on your sound taking exactly the same amount of time to play, so telling the handler to post first is a bit better. Still not ideal, however.

Another consideration is that you're re-computing uptime and adding some more time to that (200 in this case). Why not use the modulus operator on your uptime, to ensure that your next requested post time is more precisely scheduled?

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文