C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: timerについて


(過去ログ 78 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■45882 / inTopicNo.1)  timerについて
  
□投稿者/ イチ (6回)-(2010/01/21(Thu) 15:11:03)

分類:[.NET 全般] 

すみません。また質問させて頂きます。私はC#で簡単なメトロノームを作ろうとしているのですが、どうしてもテンポがずれてしまいます。
timerを使って時間を計算しているのですが、timerでは若干ズレが生じるのでしょうか?


プログラムの内容はこんな感じです。
テンポを120として実装すると、ans=5となり、0.1秒毎に実装されるtimer2_Tickにてansの値を1ずつ引いています。
ans=1となった時、音を鳴らして、カウントを1つ増やします。

timer2_Tickの呼び出し
1回目:ans=5-1=4
2回目:ans=4-1=3
3回目:ans=3-1=2
4回目:ans=2-1=1
5回目:ans==1なので音を鳴らして、カウントを増やす。

以上により、音をならすのには0.5秒かかります。120のテンポを考えると、0.5秒に1回音が鳴れば正しいので、この考えでいいのではないかと思うのですが、60秒間実装すると、カウント数は110になってしまい、少し遅いです。
これはアルゴリズムに問題があるのでしょうか?それともtimerにはズレが生じてしまうのでしょうか?
よろしくお願いします。

private void bstart_Click(object sender, EventArgs e)
{
secTime = 0;
count = 0;

x = (int)TENPO.Value; // テンポを取得
ans =(double) 60 / x ; //ディレイタイムの計算(sec)
ans = System.Math.Round(ans, 2); //ansを少数第2位までにする

ANS.Text = ans.ToString();

timer1.Start();
timer2.Start();

bstart.Enabled = false; //ボタンの2度押しを防ぐ

ans = ans*1000; //単位をmsecに直す


ans = (double)ans / 100;

}
  //0.1秒毎に呼び出されるイベント
private void timer2_Tick(object sender, EventArgs e)
{
txt2 = (double)ans / 10; //値を少数になおす ex.500→0.5
txt2 = System.Math.Round(txt2, 2);
nokori.Text = txt2.ToString();//msecをsecにして表示
CO.Text = count.ToString();



if (ans == 1)
{
count = count + 1;
CO.Text = count.ToString();
PlaySound("se_saa01.wav");
//ansの初期化
ans = (double)60 / x; //ディレイタイムの計算(sec)
ans = System.Math.Round(ans, 2); //ansを少数第2位までにする
ans = ans * 1000; //単位をmsecに直す
ans = (double)ans / 100;


}
else
{
ans = ans - 1;
label6.Text = ans.ToString();
}
}


引用返信 編集キー/
■45884 / inTopicNo.2)  Re[1]: timerについて
□投稿者/ みきぬ (725回)-(2010/01/21(Thu) 15:21:45)
Timer の Tick イベントは、「きっちり n ミリ秒経過した」ことを通知するのではなくて、
「少なくとも n ミリ秒経過した」ことを通知するものだと考えたほうがよいです。

引用返信 編集キー/
■45895 / inTopicNo.3)  Re[1]: timerについて
□投稿者/ 渋木宏明(ひどり) (1265回)-(2010/01/21(Thu) 16:36:13)
渋木宏明(ひどり) さんの Web サイト
> timerを使って時間を計算しているのですが、timerでは若干ズレが生じるのでしょうか?

あなたの言う timer が System.Windows.Forms.Timer なら、大した精度は望めません。

System.Threading.Timer や System.Timers.Timer は、System.Windows.Timer よりも扱いが難しくなりますが、タイマーの精度という点では有利です。

あと

> プログラムの内容はこんな感じです。
> テンポを120として実装すると、ans=5となり、0.1秒毎に実装されるtimer2_Tickにてansの値を1ずつ引いています。
> ans=1となった時、音を鳴らして、カウントを1つ増やします。

という手法も、微妙です。

この手順だと、「タイマーに誤差がある」場合、それが微小なものであってもどんどん累積してしまい、最終的には不都合なくらい大きな誤差になってしまいます。

引用返信 編集キー/
■45922 / inTopicNo.4)  Re[2]: timerについて
□投稿者/ イチ (7回)-(2010/01/21(Thu) 23:01:13)
No45895 (渋木宏明(ひどり) さん) に返信
> System.Threading.Timer や System.Timers.Timer は、System.Windows.Timer よりも扱いが難しくなりますが、タイマーの精度という点では有利です。
ありがとうございます。調べてみます。


>手法も、微妙です。
> この手順だと、「タイマーに誤差がある」場合、それが微小なものであってもどんどん累積してしまい、最終的には不都合なくらい大きな誤差になってしまいます。

とすれば、どのように計算するのが望ましいのでしょうか?
引用返信 編集キー/
■45926 / inTopicNo.5)  Re[3]: timerについて
□投稿者/ たくボン (331回)-(2010/01/21(Thu) 23:39:15)
No45922 (イチ さん) に返信
> >手法も、微妙です。
>>この手順だと、「タイマーに誤差がある」場合、それが微小なものであってもどんどん累積してしまい、最終的には不都合なくらい大きな誤差になってしまいます。
>
> とすれば、どのように計算するのが望ましいのでしょうか?

これはネタ?

自分の前スレを見てるんだろうか・・・。

http://bbs.wankuma.com/index.cgi?mode=al2&namber=45419

っていうか、「多少のズレ」があるメトロノームでもいいって書いてたのにねぇ:-P
引用返信 編集キー/
■45934 / inTopicNo.6)  Re[4]: timerについて
□投稿者/ 渋木宏明(ひどり) (1266回)-(2010/01/22(Fri) 00:41:10)
渋木宏明(ひどり) さんの Web サイト
> >>この手順だと、「タイマーに誤差がある」場合、それが微小なものであってもどんどん累積してしまい、最終的には不都合なくらい大きな誤差になってしまいます。
>>
>>とすれば、どのように計算するのが望ましいのでしょうか?

時間で管理するのではなく、時刻で管理するとか。

引用返信 編集キー/
■45955 / inTopicNo.7)  Re[4]: timerについて
□投稿者/ みきぬ (729回)-(2010/01/22(Fri) 10:29:47)
> これはネタ?
>
> 自分の前スレを見てるんだろうか・・・。
>
> http://bbs.wankuma.com/index.cgi?mode=al2&namber=45419
>
> っていうか、「多少のズレ」があるメトロノームでもいいって書いてたのにねぇ:-P

どのくらいの誤差なら許容可能か、にもよるよねえ。
場合によっては、Windows OS とは別のところで管理しなきゃいけないだろうし。
# よくは知らないけど、過去スレにそんな話があった覚えがある
引用返信 編集キー/
■45994 / inTopicNo.8)  Re[1]: timerについて
□投稿者/ もりお (169回)-(2010/01/22(Fri) 19:54:47)
2010/01/22(Fri) 21:22:47 編集(投稿者)
No45882 (イチ さん) に返信
> timerでは若干ズレが生じるのでしょうか?

Timer.Tick の使い方を変えてみてはいかがでしょうか。
前の時間に Interval を足していくのではなく
開始時刻からの経過時間を観測するのに用いると良いのではないでしょうか。

private System.Diagnostics.Stopwatch stopwatch;
private long previous;

private void button1_Click(object sender, EventArgs e)
{
	timer1.Interval = 20;
	previous = 0;
	stopwatch = System.Diagnostics.Stopwatch.StartNew();
	timer1.Start();
}

private void timer1_Tick(object sender, EventArgs e)
{
	long current = stopwatch.ElapsedMilliseconds / 200;

	if (previous == current)
	{
		return;
	}

	previous = current;

	if (previous % 5 == 0)
	{
		textBox1.AppendText("チーン\n");
	}
	else
	{
		textBox1.AppendText("コチ\n");
	}
}

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -