openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#31

投稿記事 by ISLe » 13年前

かなたん さんが書きました:どうやっても正確に60fpsにならないというのは、何のためのofSetFrameRate(60);なのでしょうか?
(略)
ということは、私のパソコンに入っているディスプレーアダプターであるIntel(R) HD Graphicsなどが影響している・・・とか?
毎回ぴったり60でなくても、そんなにばらついたり下がったりするものなのですか?
ばらついたり下がったりするのは性能によるものでしょうけど正確に60FPSにならないのは単にそういう実装だからです。
こちらでofSetFrameRate(60);は50FPSで一定でした。
トントンさんが指摘された理由だけでは62FPSくらいになるはずなんですよね。
他にも理由がありそうです。

指定したフレームレートにならないのはそういうものだとあきらめるしかないですね。
特に海外では固定フレームレートが一般的ではないので期待できないと思います。
フレームレートを指定しないで経過時間で進行させるのが良いでしょう。
マルチプラットフォーム向けとしてはそれが適切です。

ちなみにFPS制御を解説しているサイトをけっこうたくさん見てきましたけど60FPSを正確に刻むコードを解説してるサイトは唯の一つも見たことがないです。
ソースコードを公開しているゲーム(あるいはそれに準ずる)ソフトの中にはきちんと実装されているものもありますけどそれもわたしの知る限りほんの僅かです。
かなたん さんが書きました:soundの曲の長さが1170161msで、sound.getPosition()は1msごとに1/1170161ずつ増えていく・・・んですよね?
noteはms単位で記憶させているので、(new_time-old_time)*1170161のようにすればms単位になるはずだとおもったんですが・・・
この考えは違うのでしょうか・・・?
なぜゼロから始まるのにold_timeを引く必要があるのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#32

投稿記事 by softya(ソフト屋) » 13年前

かなたん さんが書きました:ということは、私のパソコンに入っているディスプレーアダプターであるIntel(R) HD Graphicsなどが影響している・・・とか?
毎回ぴったり60でなくても、そんなにばらついたり下がったりするものなのですか?
Intel(R) HD GraphicsのOpenGLドライバの性能次第と言ったところでしょうか。
WindowsメインであるDirectXドライバとはリソースを取り合うので性能低下は避けられないかも知れません。
あと主力であるDirectXドライバほどOpenGLドライバに開発に力を入れてるとは思えません。
言うなれば内蔵ビデオチップですのでボードのビデオカードの性能が優秀なわけではなく、OpenGL主体の高価なQuadroビデオカードほどOpenGLドライバに力を入れているはずもなくと言ったところですので60FPSが出る保証はまったくありません。
他にもopenFrameworksの問題とか色々考えられます。

試しにDXライブラリ(DirectX)のやつを動かしてみて60FPSが出るか試されてはどうでしょう?
「FPSがうまく制御できない • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?t=10547&p=84910
ISLeさんがFPS60で安定が出来るかをテストできるプログラムを添付してくれています。
これが安定していたらopenFrameworksかOpenGLが悪いって事で納得するしか無いです。
かなたん さんが書きました: soundの曲の長さが1170161msで、sound.getPosition()は1msごとに1/1170161ずつ増えていく・・・んですよね?
noteはms単位で記憶させているので、(new_time-old_time)*1170161のようにすればms単位になるはずだとおもったんですが・・・
この考えは違うのでしょうか・・・?
毎回の差分を取らず開始からの経過時間だけで管理したほうがシンプルになると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#33

投稿記事 by かなたん » 13年前

トントン さんが書きました:僕の方では、図形が反射する方?は60.2fぐらいでした。
>どうやっても正確に60fpsにならないというのは、何のためのofSetFrameRate(60);なのでしょうか?
実際中身を見てみると(見る場所あってるかわからないけど)

コード:

	
void ofAppGlutWindow::setFrameRate(float targetRate){{
~略~
        float durationOfFrame 	= 1.0f / (float)targetRate;
	millisForFrame 			= (int)(1000.0f * durationOfFrame);
となっていました。
で、この「millisForFrame」を「glutIdleFunc」に登録した関数内で
Sleep(millisForFrame)してcallしているようです。
ごめんなさい・・・
私の知識では理解できず・・・
次のフレームはmillisForFrameだけSleepしたあと呼び出されるとかそういう話ですか?
トントン さんが書きました:まぁ、16.6666...msなのが16msで呼ばれているから
「正確に60FPSにはならない」と言っているのではないかなと予想してみます。
確かに16msで呼び出していたら、それでは1フレームごとに0.6666...ms誤差が生じてしまうので、60フレームで40msの誤差が出ますね。
でも、そうなっているとすると62fpsくらいになっているはずですよね?
トントン さんが書きました:後、色の変わる円の方は、色々と変数の宣言が足りないようなので
testApp.hに宣言しているのであれば、宜しければ見せていただけませんか?
あの・・・色の変わる円ってどれのことか・・・
とりあえず、今まで載せたプログラムのtestApp.hを載せることにします。

Drum of Expart(太鼓の達人もどき)

コード:

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"


class testApp : public ofBaseApp {
	
public:
	void setup();
	void update();
	void draw();
	void exit();
	
	void keyPressed  (int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	void start();
	void checker(int push);

	ofTrueTypeFont 	point_font;
	ofTrueTypeFont 	game_font;
	int point;
	int game;
	bool menu;
	bool mouse_on;
	int count_point;
	int count_total;
	ofImage judge;
	ofImage don;
	ofImage katsu;
	char music[201];
	//int note[201]; グローバルで宣言
	int time;
	vector <int> drum[2];
	vector <float> drum_time;
	int check;
	ofSoundPlayer sound;
	ofSoundPlayer don_sound;
	ofSoundPlayer katsu_sound;
	float old_time;
	float new_time;
};

#endif
colorful_fig(跳ね返ったり変形したりする図形)

コード:

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"


class testApp : public ofBaseApp {
	
public:
	void setup();
	void update();
	void draw();
	void exit();
	
	void keyPressed  (int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	
	
};

#endif
color_cell(画面に赤・緑・青の3つの同じサイズの円を表示)

コード:

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"


class testApp : public ofBaseApp {
	
public:
	void setup();
	void update();
	void draw();
	void exit();
	
	void keyPressed  (int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	
	vector <int> cell_color[3];
	vector <int> cell_size;
	vector <ofPoint*> cell_pos;
	vector <ofPoint*> cell_speed;	
};

#endif
私がこのトピックで載せたプログラムはこの3つのつもりですが・・・他にも載せましたっけ?

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#34

投稿記事 by かなたん » 13年前

ISLe さんが書きました: 指定したフレームレートにならないのはそういうものだとあきらめるしかないですね。
特に海外では固定フレームレートが一般的ではないので期待できないと思います。
フレームレートを指定しないで経過時間で進行させるのが良いでしょう。
マルチプラットフォーム向けとしてはそれが適切です。
softya(ソフト屋) さんが書きました:Intel(R) HD GraphicsのOpenGLドライバの性能次第と言ったところでしょうか。
WindowsメインであるDirectXドライバとはリソースを取り合うので性能低下は避けられないかも知れません。
あと主力であるDirectXドライバほどOpenGLドライバに開発に力を入れてるとは思えません。
言うなれば内蔵ビデオチップですのでボードのビデオカードの性能が優秀なわけではなく、OpenGL主体の高価なQuadroビデオカードほどOpenGLドライバに力を入れているはずもなくと言ったところですので60FPSが出る保証はまったくありません。
他にもopenFrameworksの問題とか色々考えられます。
仕様ですか・・・
できるだけスペックなどによる個体差が出ないようにした方がいいというのはわかりますが、私的にはフレームレートを頼れる方が作りやすかったです・・・
でも、今回いろいろとやっていてフレームレートは当てにならないので、きちんと経過時間などを利用して作れるようになりたいと思います。
softya(ソフト屋) さんが書きました:試しにDXライブラリ(DirectX)のやつを動かしてみて60FPSが出るか試されてはどうでしょう?
これが安定していたらopenFrameworksかOpenGLが悪いって事で納得するしか無いです。

そのプログラムを試してみました。
最初のうちは59.いくつ~61.いくつくらいまでをふらふらしているようでしたが、しばらくすると60ちょうどで安定するようになりました。
ということは、openFrameworksかOpenGLが悪いってことですね・・・
ISLe さんが書きました:ちなみにFPS制御を解説しているサイトをけっこうたくさん見てきましたけど60FPSを正確に刻むコードを解説してるサイトは唯の一つも見たことがないです。
ソースコードを公開しているゲーム(あるいはそれに準ずる)ソフトの中にはきちんと実装されているものもありますけどそれもわたしの知る限りほんの僅かです。
そんなにフレームレートは当てにならないのに、なぜ設定したり利用したりするのですか?
他に利用できるようなものはなかったのでしょうか・・・?
ISLe さんが書きました:なぜゼロから始まるのにold_timeを引く必要があるのでしょうか?
音のタイミングを記憶させているnoteは、それぞれの音の間隔をmsで記憶させているので、前の音を流してからどれくらいたったのかを取得するべくold_timeを引いているんです。
この差分を利用した考えがよくないのかな・・・
softya(ソフト屋) さんが書きました:毎回の差分を取らず開始からの経過時間だけで管理したほうがシンプルになると思います。
noteに差分を記憶させるほうが、noteを見ていて見やすくていいんですよね。
差分でなくて開始からどれくらいで考えようかと思ったこともありましたが、次を流したりするのに前との差文が分かればnoteは差分のままでも行けると思ったので、noteをわかりやすくしておきたいと言うだけでやめにしていました。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#35

投稿記事 by ISLe » 13年前

かなたん さんが書きました:そんなにフレームレートは当てにならないのに、なぜ設定したり利用したりするのですか?
他に利用できるようなものはなかったのでしょうか・・・?
フレームレートが当てにならないわけではないです。
現にわたしの自作のフレームワークは正確にフレームレートを刻みます。

フレームレートをモニタのリフレッシュレートに依存していたり、タイミングの計算が正確ではないプログラムが巷にあふれているだけの話です。

それと同じようにopenFrameworksのフレームレート設定が当てにならないわけですね。
それがなぜなのかはopenFrameworksの中の人しか分からないことですが。

非力なハードウェアでは処理が間に合わないのでそもそもフレームレートを正確に維持できない(しようとするだけ無駄)という状況もあります。
固定フレームレートは特定のハードウェアだけを対象にする場合や十分に処理能力のあるハードウェアを対象にする場合でなければうまく機能しないのです。
そういう意味ではopenFrameworksが最初から正確なフレームレートを刻む気なんてないとしても仕方がないと思います。
かなたん さんが書きました:音のタイミングを記憶させているnoteは、それぞれの音の間隔をmsで記憶させているので、前の音を流してからどれくらいたったのかを取得するべくold_timeを引いているんです。
この差分を利用した考えがよくないのかな・・・
old_timeは前のフレームで記録した再生位置ですよね。
noteがひとつ前からの差分であることとどうしてつながるのでしょうか。
old_timeはnoteの基準にはなりません。
過去のnoteを蓄積したものと再生位置を比較するしかないのでは?

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#36

投稿記事 by ISLe » 13年前

openframeworkslibプロジェクトのプロパティで、プリプロセッサの定義にWIN32_HIGH_RES_TIMINGを追加するとtimeBeginPeriod(1);で初期化されて精度が上がるようになってました。

ただしofAppRunner.cppがコンパイルエラーになるので

コード:

#ifdef TARGET_WIN32
    #include <mmsystem.h>
#endif
というコードを適当なところに追加してください。

openFrameworksはバージョン0071を使いました。

精度が上がってもどのみち正確ではないしフレームレートに依存しないようにしたほうが良いと思います。
コンパイルエラーになるのを放置しているくらいですからね。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#37

投稿記事 by かなたん » 13年前

ISLe さんが書きました:フレームレートが当てにならないわけではないです。
現にわたしの自作のフレームワークは正確にフレームレートを刻みます。
確かにISLeさんのプログラムは正確でした。
私の言葉が足りずすいません・・・
openFrameworksはなんで60に設定しても50だったり32だったりしてしまうようなフレームレートを当てにしているんだろうなと。
MFCのタイマーはms単位ですよね。
今まで正確なタイミングを要求するようなものは作ったことないのですが、あれも遅延することあるのでしょうか?
ISLe さんが書きました:フレームレートをモニタのリフレッシュレートに依存していたり、タイミングの計算が正確ではないプログラムが巷にあふれているだけの話です。

それと同じようにopenFrameworksのフレームレート設定が当てにならないわけですね。
それがなぜなのかはopenFrameworksの中の人しか分からないことですが。

非力なハードウェアでは処理が間に合わないのでそもそもフレームレートを正確に維持できない(しようとするだけ無駄)という状況もあります。
固定フレームレートは特定のハードウェアだけを対象にする場合や十分に処理能力のあるハードウェアを対象にする場合でなければうまく機能しないのです。
そういう意味ではopenFrameworksが最初から正確なフレームレートを刻む気なんてないとしても仕方がないと思います。
そうですか・・・
フレームレートにはスペック差があるにもかかわらず、無視してでも利用しているんですよね?
フレームレートって、そんなんでも利用したくなるものなのですか?
ISLe さんが書きました:old_timeは前のフレームで記録した再生位置ですよね。
noteがひとつ前からの差分であることとどうしてつながるのでしょうか。
old_timeはnoteの基準にはなりません。
過去のnoteを蓄積したものと再生位置を比較するしかないのでは?
old_timeは太鼓を流し始めたら書き換えるようになっています。
決して、毎フレーム書き換えているわけではありません。
いや・・・私がそう書いているつもりでも、あのソースはそうはなっていないのでしょうか?
old_timeは新しく太鼓を流すごとにnew_timeに書き変えされるようにしているつもりで、そうしたら(new_time-old_time)*1170161>=note[time]が成り立つ頃にはまた新たな太鼓を流していいはずで、そのときにはまたold_timeはnew_timeに書き変えされるようにしているつもりなのですが・・・
note蓄積とnew_timeを比較する方が、誤差が少ないでしょうか?

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#38

投稿記事 by かなたん » 13年前

ISLe さんが書きました:openframeworkslibプロジェクトのプロパティで、プリプロセッサの定義にWIN32_HIGH_RES_TIMINGを追加するとtimeBeginPeriod(1);で初期化されて精度が上がるようになってました。

ただしofAppRunner.cppがコンパイルエラーになるので

コード:

#ifdef TARGET_WIN32
    #include <mmsystem.h>
#endif
というコードを適当なところに追加してください。

openFrameworksはバージョン0071を使いました。

精度が上がってもどのみち正確ではないしフレームレートに依存しないようにしたほうが良いと思います。
コンパイルエラーになるのを放置しているくらいですからね。
せっかくですが、コンパイルエラーとかになるくらいなら、ますますフレームレートは頼らないので・・・
今のままでも、計算とか正しく行えば曲との同期がきちんと取れますよね?
うまくいっていないのは私が間違えているだけで・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#39

投稿記事 by softya(ソフト屋) » 13年前

かなたん さんが書きました:確かにISLeさんのプログラムは正確でした。
私の言葉が足りずすいません・・・
openFrameworksはなんで60に設定しても50だったり32だったりしてしまうようなフレームレートを当てにしているんだろうなと。
MFCのタイマーはms単位ですよね。
今まで正確なタイミングを要求するようなものは作ったことないのですが、あれも遅延することあるのでしょうか?
openFrameworksで、もし正確にフレームレートを刻めないPCが有った場合はアサートすべきなんでしょうか?
openFrameworksの中の人の考え方次第ですが出来ないものは仕方ないとするのも考え方の一つです。
例えば割り切れて速度的に十分な余裕が有るフレームレート20とかにすれば、ほとんど正確になるのでは?

ofSetFrameRateの説明もこう書いてありますし
Attempts to set the frame rate to a given target by sleeping a certain amount per frame.
The results of this may vary based if vertical sync is enabled or disabled (either at the card level or via code), because this locks the drawing to intervals where the screen refreshes.
けっして保証するとか書いてないですよね。

それとMFCと言うかWin32APIのタイマーは、かなり不正確です。
そもそもWM_TIMERメッセージで処理されますしマルチプロセス/マルチスレッド下で動いているのでms台の正確さは求めてはいけません。
これは非リアルタイムOSでマルチタスクOSであるWindowsの避けれない仕様です。
かなたん さんが書きました:そうですか・・・
フレームレートにはスペック差があるにもかかわらず、無視してでも利用しているんですよね?
フレームレートって、そんなんでも利用したくなるものなのですか?
高速で快適なPCならそもそも気にならないでしょう。
低速なPCなら低FPSで安定しますので、そうやって利用します。
アニメーションのためにはできるだけ正確なフレームレートであったほうがスムーズに動きますし、フレームレートを使ったほうが管理が楽ですよね。

で、Windowsでゲームを作るなら安定した速度の出るDirectxを利用したほうが良いと思います。
DirectXのラッパーであるDXライブラリを使うというのは選択肢にはないのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#40

投稿記事 by かなたん » 13年前

softya(ソフト屋) さんが書きました:openFrameworksで、もし正確にフレームレートを刻めないPCが有った場合はアサートすべきなんでしょうか?
openFrameworksの中の人の考え方次第ですが出来ないものは仕方ないとするのも考え方の一つです。
例えば割り切れて速度的に十分な余裕が有るフレームレート20とかにすれば、ほとんど正確になるのでは?
"実行時はフレームレートは当てにならないんだから、自分が設定したフレームレートを当てにプログラムを組むな。"
というのはわかってますが、自分で設定した設定(今回のフレームレートに限らず)通りに動いてほしいと私は思うんですよ。
GIFアニメーションを作るときは、1コマごとに表示時間を設定して作りますよね。
といっても私は1秒何コマのものを作っているわけではないので確かめたことないのですが、たぶんその設定通りのはずですよね。
楽譜にはたいていテンポや拍子が書いてあって、演奏するときはそのテンポや拍子を元に速さを決めて演奏しますよね。
またテンポや拍子が分かれば、1拍子何秒などの情報を求めることもできますよね。
この情報って、誰が見ても基本変わらないですよね?
softya(ソフト屋) さんが書きました:それとMFCと言うかWin32APIのタイマーは、かなり不正確です。
そもそもWM_TIMERメッセージで処理されますしマルチプロセス/マルチスレッド下で動いているのでms台の正確さは求めてはいけません。
これは非リアルタイムOSでマルチタスクOSであるWindowsの避けれない仕様です。
やはりSetTimerでセットした通り正確に動いているわけではないのですね。
タイマーってデフォルトだと誤差も当たり前なのですね・・・
softya(ソフト屋) さんが書きました:高速で快適なPCならそもそも気にならないでしょう。
低速なPCなら低FPSで安定しますので、そうやって利用します。
アニメーションのためにはできるだけ正確なフレームレートであったほうがスムーズに動きますし、フレームレートを使ったほうが管理が楽ですよね。
アニメーションの時には、私は先ほど言った通り1秒あたり何コマでなく1コマ何秒表示させるのかで作っているので、フレームレートというより1コマ何秒の設定ができればいいんです。
いっそのこと、sleepなどでコマ間にwaitを入れるんでもいいくらい。
テレビなどのアニメーションではきちんと1秒何フレームで作っているでしょうから、確かにフレームレートを利用する方が楽なんでしょうけど。
softya(ソフト屋) さんが書きました:で、Windowsでゲームを作るなら安定した速度の出るDirectxを利用したほうが良いと思います。
DirectXのラッパーであるDXライブラリを使うというのは選択肢にはないのでしょうか?
最近のプログラミングの最終目的はkinectとWindowsでOpenNI・openFrameworksなどを使ってプログラミングしたいんです。
知り合いのプログラミングの手伝いということで一緒にやっていて、週一しか予定が合わず、また私はkinectを持っていないというところから、一緒にやる日でないときは自分なりにkinectでなにがで作れそうかとか使用するプログラミング言語で何ができるのかを調べたり試したりしています。
openFrameworksに出会ったとき、openFrameworksはなにができるんだろう?と本を借りてみたところ、いろいろと面白そうなものができそうだなと思って気に入ったんです。
このプログラムをkinectと連動させるかどうかは、ポーズ認識などどの程度できるようになるかで変わりますが、とりあえずopenFrameworksでどういうことができるのかを試したりアイデアを実現させてみたいと思っていろいろとやっているところです。
というわけで、今回はDXライブラリなどを使うというのは選択肢にないんです。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#41

投稿記事 by かなたん » 13年前

太鼓を流すのを曲のポジションに同期させている話ですが、
プログラムの考えは同じに曲の長さを115ピッタリにしてみたところ、素早く流れてしまうことはなくなったのですが、それでも少し遅れてしまっていました。
もしかして、前の時は桁を間違えた・・・かな?
そこで、ISLeさんが言っていたようにnoteの蓄積とnow_timeを比較するようにしてみたところ、私は誤差に気づかなくなりました。
毎回の差分に幾分か誤差があり、その誤差が誤差を読んで目立つようになっていたのだと思います。
これで対こと曲をそろえることができたので、「プログラムで曲を流すと、他の処理が遅くなる。」という問題は解決ということで。

以下が、うまく同期できたプログラムソース(testApp.cpp)です。

コード:

#include "testApp.h"

//--------------------------------------------------------------

int speed=5;
int note[201]={750,250,750,250,500,500,1000, //ドはドーナッツのド
				750,250,250,250,250,250,2000, //レはレモンのレ
				750,250,750,250,500,500,1000, //ミはみんなのミ
				750,250,250,250,250,250,2000, //ファはファイトのファ
				750,250,250,250,250,250,2000, //ソは青い空
				750,250,250,250,250,250,2000, //ラはラッパのラ
				750,250,250,250,250,250,1500, //シはしあわせよ
				250,250,500,500,500,500,2000, //さぁ歌いましょう
				750,250,750,250,500,500,1000, //どんなときにも
				750,250,250,250,250,250,2000, //列を組んで
				750,250,750,250,500,500,1000, //みんな楽しく
				750,250,250,250,250,250,2000, //ファイトをもって
				750,250,250,250,250,250,2000, //空を仰いで
				750,250,250,250,250,250,2000, //ラララララララ
				750,250,250,250,250,250,1500, //幸せの歌
				250,250,500,500,500,500,1000,1000,500, //さぁ歌いましょう
				500,500,500,500,500,500,500,500, //ドレミファソラシド
				500,500,500,500,500,500,500, //ドシラソファミレ
				500,500,1000,500,500,1000, //ドミミ ミソソ
				500,500,1000,500,500,1000, //レファファ ラシシ
				250,250,500,250,250,500,250,250,500,250,250,500, //ドミミ ミソソ レファファ ラシシ
				250,250,500,250,250,500,250,250,500,250,250,500, //ドミミ ミソソ レファファ ラシシ
				500,500,500,500,500,500,500,500,500,500,500,500,2000, //ソドラファミドレ
				500,500,500,500,500,500,500,500,500,500,500,500,2250, //ソドラシドレド
				250,250,250,250,250,250,250,1000,1000,1500}; //ドレミファソラシド ソ ド

void testApp::setup()
{
	ofSetLogLevel(OF_LOG_VERBOSE);
	ofLog(OF_LOG_VERBOSE, "Start setup()");
	
	// 画面の設定
    ofSetFrameRate(60);
    ofSetCircleResolution(128);
    ofBackground(255, 255, 255);
	ofSetWindowShape(480, 360);
    ofEnableSmoothing();

	//フォント読み込み
	point_font.loadFont("vag.ttf", 18); //ソリューションパス\bin\data内にフォントを用意
	game_font.loadFont("vag.ttf", 32);

	//ゲーム画面の設定
	menu=true; //メニューの表示
	mouse_on=false; //マウスはボタンの外

	//画面の混合の設定を加算合成にする
	ofEnableAlphaBlending();
	glEnable(GL_BLEND);

	//画像データの読み込み
	judge.loadImage("judge.png");
	don.loadImage("don.png");
	katsu.loadImage("katsu.png");

	//曲の読み込み
	strcpy(music,"dddkddddkdkdkddkkdkdkdkdkdkdddddddkkkkkkkdddddddkkkdddkddddkddddkdkdkddkkdkdkdkdkdkdddddddkkkkkkkdddddddkkkdddkdkkdkdkddddkdkdkkkdkkkdddkkkdddkkkdddkkkdddkkkdddkkkddddkkddkkddkkdddkkddkkddkkdddkdkdkdkd");
	//各音の長さはグローバルで
	time=0; //0番目の太鼓から
	sound.loadSound("Sound_of_doremi.wav");
	sound.setLoop(false);
	don_sound.loadSound("don.wav");
	katsu_sound.loadSound("katsu.wav");
}

//--------------------------------------------------------------

void testApp::update()
{
	if(menu==false && game==0){//ゲームの最中なら
		new_time=sound.getPosition();
		if(new_time*115000>=musicpos){ //次の太鼓を流してよくなるまで待ったら
			time++; //次の太鼓を流す
			if(time<202){
				old_time=new_time;
				if(music[time]=='d'){
					drum[0].push_back(0);
				}
				else{
					drum[0].push_back(1);
				}
				drum[1].push_back(640);
				drum_time.push_back(new_time);
				musicpos=musicpos+note[time];
			}
		}
		if(drum[1].size()>0){ //終わりではなくて、1つ以上太鼓が画面にあるなら
			for(int n=0;n<drum[1].size();n++){
				drum[1][n]=40+(int)(0.3*(2000-(new_time-drum_time[n])*115000)); //太鼓を流す
			}
			if(drum[1][0]<0){
				if(check==0){ //もし太鼓が素通りされていたら
					point=point-50;
					check=-2;
				}
			}
			if(drum[1][0]<-40){ //画面から見えなくなったら
				for(int n=1;n<drum[1].size();n++){
					drum[0][n-1]=drum[0][n];
					drum[1][n-1]=drum[1][n];
					drum_time[n-1]=drum_time[n];
				}
				drum[0].pop_back();
				drum[1].pop_back();
				drum_time.pop_back();
				check=0;
			}
		}
	}
}

void testApp::draw() //setupで決めたフラッシュレートに従って呼び出される
{
	if(menu==true){ //メニューを表示する

		ofSetHexColor(0x000000);
		game_font.drawString("Expert of Drum",100,150);
		if(mouse_on==true){
			ofSetColor(0,0,0);
			ofRect(198,177,60,25);
			ofSetColor(255,255,255);
			ofRect(199,178,58,23);
		}
		ofSetHexColor(0x000000);
		point_font.drawString("Start",200,200);
	}
	else{
		//譜面のバーを描画
		ofSetColor(0,0,0);
		ofRect(0,147,480,3); //上バー
		ofRect(0,210,480,3); //下バー

		//画像で使える色を設定
		ofSetColor(255,255,255);//全色可

		//判定枠の描画
		judge.draw(40,160);

		//譜面に合わせてドンやカツを表示
		if(drum[0].size()>0){
			for(int n=0;n<drum[0].size();n++){
				if(drum[0][n]==0){
					don.draw(drum[1][n],160);
				}
				else{
					katsu.draw(drum[1][n],160);
				}
			}
		}

		//文字等の描画
		ofSetHexColor(0x000000);
		switch (check){
			case -2:
				point_font.drawString("Very Bad...",40,120);
				break;
			case -1:
				point_font.drawString("Bad...",40,120);
				break;
			case 1:
				point_font.drawString("Good!",40,120);
				break;
			case 2:
				point_font.drawString("Very Good!",40,120);
				break;
		}
		char points[20];
		sprintf(points,"Point : %d",point);
		point_font.drawString(points,440-point_font.getStringBoundingBox(points,0,0).width,120);
	}
}

//--------------------------------------------------------------

void testApp::keyPressed(int key)
{
	// キーが押された時の処理
	if(menu==false && game==0){ //ゲームの最中であるなら
				if(time>=14){
					time=time;
				}
		if(drum[0].size()>0){
			switch (key)
			{
				case 'd':
					don_sound.play();
					if(drum[1][0]>=0 && drum[1][0]<=100){
						testApp::checker(0);
					}
					break;
				case 'k':
					katsu_sound.play();
					if(drum[1][0]>=0 && drum[1][0]<=100){
						testApp::checker(1);
					}
					break;
			}
		}
	}
	
}

void testApp::exit()
{
	ofLog(OF_LOG_VERBOSE, "End Application");
}

//--------------------------------------------------------------


//--------------------------------------------------------------

void testApp::keyReleased(int key)
{
	// キーがリリースされた時の処理
}

//--------------------------------------------------------------

void testApp::mouseMoved(int x, int y )
{
	// マウスが動かされた時の処理
	if((x>=198 && x<=258) && (y>=179 && y<=202)){
		mouse_on=true;
	}
	else{
		mouse_on=false;
	}
}

//--------------------------------------------------------------

void testApp::mouseDragged(int x, int y, int button)
{
	// マウスがドラッグされた時の処理
}

//--------------------------------------------------------------

void testApp::mousePressed(int x, int y, int button)
{
	// マウスボタンが押された時の処理
	if(menu==true && (x>=198 && x<=258) && (y>=179 && y<=202)){
		mouse_on=0;
		game=0;
		menu=false;
		testApp::start();
	}
	else if(game!=0){
		menu=true;
	}
}

//--------------------------------------------------------------

void testApp::mouseReleased(int x, int y, int button)
{
	// マウスボタンがリリースされた時の処理
}

//--------------------------------------------------------------

void testApp::windowResized(int w, int h)
{
	// ウィンドウがリサイズされた時の処理
	ofSetWindowShape(480, 360);
}

void testApp::start(){

	//得点の初期化
	point=0;
	count_point=0;
	count_total=0;
	drum[0].push_back(0);
	drum[1].push_back(640);
	sound.play();
	old_time=sound.getPosition();
	drum_time.push_back(old_time);
	musicpos=note[time];
}

void testApp::checker(int push){
	if(push==drum[0][0]){
		if(drum[1][0]>15 && drum[1][0]<55){
			point=point+100;
			check=2;
		}
		else if(drum[1][0]>0 && drum[1][0]<80){
			point=point+50;
			check=1;
		}
		else if(drum[1][0]>-20 && drum[1][0]<100){
			point=point;
			check=-1;
		}
	}
	else{
		check=-1;
	}
	for(int n=1;n<drum[1].size();n++){
		drum[0][n-1]=drum[0][n];
		drum[1][n-1]=drum[1][n];
		drum_time[n-1]=drum_time[n];
	}
	drum[0].pop_back();
	drum[1].pop_back();
	drum_time.pop_back();
}

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#42

投稿記事 by かなたん » 13年前

あ。
解決押そうと思っていたのに忘れてました。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#43

投稿記事 by ISLe » 13年前

かなたん さんが書きました:フレームレートにはスペック差があるにもかかわらず、無視してでも利用しているんですよね?
フレームレートって、そんなんでも利用したくなるものなのですか?
逆に高スペックなハードでは更新頻度を抑える効果があります。
何も変化がないのに描画だけをすごい速さで繰り返しても無駄ですからね。
バッテリーの消耗にも繋がりますし。


Windows98のころはタイマーの精度自体がどうしようもなかったですが、Windows2000になると1ミリ秒の精度は保証されるようになってたと思います。
SetTimerのイベントが遅れるのはイベントという仕組みを使っているから起こることであってタイマーの精度とは別の話です。
いまは確実に1ミリ秒以下の精度があるのでそれなりに工夫すれば正確なタイミングを取ることは可能です。


アニメにしても音楽にしても絶対的な速さではなくて相対的な速さです。
時間が一定の速さで流れていると考えるのは間違いです。
いまここにいる自分の感じる一秒が、外の世界から見たら1分の出来事かもしれません。

音楽に合わせて進めるというのは、例えば1分の音楽の演奏が始まってから終わるまでが1分間と考える、ということです。
実際の演奏に2分かかったとしてもそれを1分間として処理を進めるのです。
逆に考えればテンポを変えることができるようにするということになります。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#44

投稿記事 by ISLe » 13年前

音楽再生とメインプログラム(のフレームレート)は時間軸が異なります。
なのですり合わせが必要です。

すべて再生した時点、つまりofSoundPlayer::getPositionが1を返す時点が再生時間(ミリ秒)とすることですり合わせができています。
なので実際にかかった再生時間にかかわらず音楽とタイミングが合うわけです。

公式サイトのリファレンスを見ただけなので機能するか分かりませんが、ofSoundPlayer::setSpeedで音楽の再生速度を変えるだけでゲームのテンポも合わせて変わるはずです。
試してみてください。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#45

投稿記事 by かなたん » 13年前

ISLe さんが書きました:逆に高スペックなハードでは更新頻度を抑える効果があります。
何も変化がないのに描画だけをすごい速さで繰り返しても無駄ですからね。
バッテリーの消耗にも繋がりますし。
確かに、変化がないのに更新しているのは無駄ですよね。
でも、変化が激しい時とそうでないときとなんてたぶんプログラムにはわからないですよね?
激しいときでも抑えられてはプログラムの組み方によっては困るじゃないですか。
ISLe さんが書きました:Windows98のころはタイマーの精度自体がどうしようもなかったですが、Windows2000になると1ミリ秒の精度は保証されるようになってたと思います。
SetTimerのイベントが遅れるのはイベントという仕組みを使っているから起こることであってタイマーの精度とは別の話です。
いまは確実に1ミリ秒以下の精度があるのでそれなりに工夫すれば正確なタイミングを取ることは可能です。
タイマーとしては精度が上がってきているのに、イベントで処理しているから精度以上に誤差があるのですね。
ISLe さんが書きました:アニメにしても音楽にしても絶対的な速さではなくて相対的な速さです。
時間が一定の速さで流れていると考えるのは間違いです。
いまここにいる自分の感じる一秒が、外の世界から見たら1分の出来事かもしれません。
今の1分1秒も誰かが定めた物を頼りにしていますよね。
1年はぴったり365日ではなく、幾分か誤差があるので、4年に1度うるう年と言って1年が366日ある年があるんですよね。
その1年は、地球では地球が公転で太陽の周りを1周するのを基準にしているんですよね。
だから、よその星では1年が365日以上もっとある星もあったりするんですよね。
ISLe さんが書きました:音楽に合わせて進めるというのは、例えば1分の音楽の演奏が始まってから終わるまでが1分間と考える、ということです。
実際の演奏に2分かかったとしてもそれを1分間として処理を進めるのです。
逆に考えればテンポを変えることができるようにするということになります。
同期の頼りにしているもののテンポを変えたら、その同期全体でテンポが変わるはずですね。
そしてきちんと同期していないものでは、誤差が発生したりするんですよね。
ISLe さんが書きました:音楽再生とメインプログラム(のフレームレート)は時間軸が異なります。
なのですり合わせが必要です。

すべて再生した時点、つまりofSoundPlayer::getPositionが1を返す時点が再生時間(ミリ秒)とすることですり合わせができています。
なので実際にかかった再生時間にかかわらず音楽とタイミングが合うわけです。
私はすべてミリ秒かなにかできちんと管理できるなら管理しやすいのにと思うんですけど、そううまくいかないから同期したいものの中でタイミングを自由に変えられるものを自由に変えずらいものに合わせて管理するんですよね。
ISLe さんが書きました:公式サイトのリファレンスを見ただけなので機能するか分かりませんが、ofSoundPlayer::setSpeedで音楽の再生速度を変えるだけでゲームのテンポも合わせて変わるはずです。
試してみてください。
setSpeedで速度を2倍にしたり0.5倍にしたりしてみました。
きちんと曲と同期できているようで、太鼓も曲に合わせて速度が変わることが確認できました。
でも、setSpeedって正確にはテンポを早くするというかピッチを上げたというか、1より大きくすると音が高くなり、1より小さくすると音が低くなるんですね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#46

投稿記事 by softya(ソフト屋) » 13年前

少なくともopenFrameworks 前提とするなら、openFrameworks の枠組みの中で動作するように書く必要があります。
あと起動時にテストして安定できるフレームレートを調べてから、そのPCで安定して表示できるフレームレートを選ぶというのも手です。
まぁ、音楽再生に合わせて太鼓の位置を調整してやれば相当変動がない限り問題のない表示ができるのでは無いかと思います。
※ 昔のゲーム機では30FPSとかザラだったので、30FPS程度でも問題なくプレイ出来ると思います。

【こっちも補足】
画一な性能のゲーム機と違いPCの場合はPC毎の性能差が激しいので可能な限り低い性能に合わせたほうが快適に遊べる人が増えることになります。
あえて不利なOpenGL系を選択するわけですから、より悪条件に合わせる必要が出てきます。
その知り合いの方とも相談して、低いスペックでの動作をどうするかを決められたほうが良いと思います。


ちなみに音楽の再生速度を変えるとピッチが変化します。これは周波数を上げたり下げたりしているのと同じだからです。
[補足] 音というのは波ですが、周波数は波の間隔で決まりますので再生速度を上げると波の間隔が詰まります。つまり周波数が上がります。
これはドップラー効果と呼ばれる救急車のサイレンが近づいてくると高くなり(車の速度分だけ波の間隔が狭まる)遠ざかると低くなる(車の速度分だけ波の間隔が広がる)のと同じ原理です。
周波数を変えないまま、再生速度だけ上がるのはピッチダウンを行いながら再生しなければいけないので実は高度な技術となります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#47

投稿記事 by ISLe » 13年前

かなたん さんが書きました:でも、変化が激しい時とそうでないときとなんてたぶんプログラムにはわからないですよね?
激しいときでも抑えられてはプログラムの組み方によっては困るじゃないですか。
なぜ激しいときに抑えられてしまうことになるのでしょう?
フレームレートはそれ以上の更新速度にはしてほしくないという意味でもあります。
これ以上速くても無駄というのは自分で作ったものをテストプレイしていて分かりますよね(あるいは作る前から決めている)。
アクション性の低いパズルゲームあたりは30FPSでも十分過ぎます。

極端な話リフレッシュレートが1000Hzを超えると1フレームあたりの時間が1ミリ秒未満になってしまうので、ミリ秒精度を前提としたプログラムは動かなくなる可能性があります。
かなたん さんが書きました:今の1分1秒も誰かが定めた物を頼りにしていますよね。
1年はぴったり365日ではなく、幾分か誤差があるので、4年に1度うるう年と言って1年が366日ある年があるんですよね。
その1年は、地球では地球が公転で太陽の周りを1周するのを基準にしているんですよね。
だから、よその星では1年が365日以上もっとある星もあったりするんですよね。
それは単位の基準の話ですね。
相対的速度の話ではありません。
そもそもこの世界にいるわたしたちにはこの世界の外から観測するすべがありませんからこの世界の時間軸上の時刻しか読み取ることができません。
かなたん さんが書きました:私はすべてミリ秒かなにかできちんと管理できるなら管理しやすいのにと思うんですけど、そううまくいかないから同期したいものの中でタイミングを自由に変えられるものを自由に変えずらいものに合わせて管理するんですよね。
最終的に全部ミリ秒で管理してうまくいったではないですか。
うまくいかないのは1ミリ秒がどこでも同じ長さだと思っていることが理由です。
今回のプログラムで言うと、
  • 再生されている音楽
  • フレームレート管理下のメインルーチン
  • かなたんさん
が観測する1ミリ秒という時間がそれぞれ違うのです。
そして、かなたんさんは再生されている音楽やフレームレート管理下のメインルーチンの時間軸をその世界の外から観測しているのです。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#48

投稿記事 by かなたん » 13年前

一緒にやっている人は芸術関係の人で、あまりプログラミングの知識を持ち合わせていないようです。
Flashやphp、htmlを使ったことはあるというのは聞いています。
kinectハックだけでなくC言語系やopen~はやったことないようです。
参考にしている「キネクトハッカーズマニュアル」にopenFrameworksを使ってのプログラミングが載っていて、それを使って作った例も載っていました。
その人は、その作った例までのことはできないだろうけど、openFrameworksを使えばいろいろなことができるようになると思っています。
というか、OpenNIとOpenCVでどういうのが作れるのだろう?状態です。
私も似たようなことを思っていたりします。
kinectハックはその人のパソコン(Windows Vistaのノート)を中心にやっています。
まだ実際に自分たちでプログラムを組んでみるところまで行っていない―環境準備等の段階で詰まっている(サンプルのビルドが通らない・・・)ので、具体的にどういうのを作りたいかは定まっていません。
openFrameworksをkinectハックで利用したサンプルのビルドで詰まっているので、このままうまくいかないのであれば、openFrameworksを使ったりするのをあきらめてOpenNIとOpenCVだけでやることにしてみましょうか?という流れになりつつもあります。
とりあえず、どの方法でkinectハックするにしてもそのVista上できちんと実行できれば問題ないです。

フレームレートを30に下げて計測してみたところ、fpsは、30.303030かそうでないかでした。

コード:

OF: OF_VERBOSE: Start setup()
fps:21.868787
start
fps:30.303030
fps:30.273438
fps:30.155642
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.332681
fps:30.273438
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.214425
fps:30.332681
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.214425
fps:30.273438
fps:30.243902
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.332681
fps:30.243902
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.126336
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.332681
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.243902
fps:30.185005
fps:30.303030
fps:30.243902
fps:30.273438
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.243902
fps:30.303030
fps:30.332681
fps:30.273438
fps:30.303030
fps:30.243902
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.332681
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.332681
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.185005
fps:30.273438
fps:30.332681
fps:30.303030
fps:30.332681
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.273438
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.273438
fps:30.303030
fps:30.303030
fps:30.155642
fps:30.185005
fps:30.303030
fps:30.243902
fps:30.155642
fps:30.303030
OF: OF_VERBOSE: End Application
続行するには何かキーを押してください . . .
また、さらに半分の15にして計測してみると、その半分の15.151515かそうでないかでした。

コード:

OF: OF_VERBOSE: Start setup()
fps:9.813543
fps:15.151515
fps:15.151515
start
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.108593
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.122873
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.165877
fps:15.137181
fps:15.122873
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.165877
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.122873
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.108593
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.165877
fps:15.151515
fps:15.165877
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.137181
fps:15.151515
fps:15.009381
fps:15.094340
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.165877
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.151515
fps:15.137181
fps:15.151515
fps:15.151515
fps:15.165877
OF: OF_VERBOSE: End Application
続行するには何かキーを押してください . . .
下げれば下げるほど設定値に近づくというより、フレームレートを下げると誤差も同じ割合下がるというだけのようですね。
きちんとぴったりにさせるには、自分で手を加えないといけないと。
softya(ソフト屋) さんが書きました:ちなみに音楽の再生速度を変えるとピッチが変化します。これは周波数を上げたり下げたりしているのと同じだからです。
[補足] 音というのは波ですが、周波数は波の間隔で決まりますので再生速度を上げると波の間隔が詰まります。つまり周波数が上がります。
これはドップラー効果と呼ばれる救急車のサイレンが近づいてくると高くなり(車の速度分だけ波の間隔が狭まる)遠ざかると低くなる(車の速度分だけ波の間隔が広がる)のと同じ原理です。
周波数を変えないまま、再生速度だけ上がるのはピッチダウンを行いながら再生しなければいけないので実は高度な技術となります。
普通に再生速度を変えただけでは波が変わってしまうので、作曲ソフトのように音はそのままにテンポを変化させるというのは高度な動きなのですね。
以前ビープ音を扱ってみたとき、音の変化と同様に音量の変化を感じた(プログラム内外で音量を変えたつもりはない)のですが、それもこういうのが関係しているのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#49

投稿記事 by softya(ソフト屋) » 13年前

openFrameworksの問題は、動作する環境次第で60fpsにするのが難しいこと(30fpsなら多分大丈夫)とopenFrameworks自体のフレームレート管理が適当なことでしょう。あとkinectが動作するまで持っていけるかは技術的なスキルとの兼ね合いです。そこをどう判断するかですね。

芸術関係で多く使われるprocessingと互換性が高いと思われるopenFrameworksですのでメインの人の使いこなせる確率が高そうではあります。他(DXライブラリ)でやってもkinectが簡単かは微妙ですが60fpsは出しやすくなると思います。
かなたん さんが書きました:普通に再生速度を変えただけでは波が変わってしまうので、作曲ソフトのように音はそのままにテンポを変化させるというのは高度な動きなのですね。
以前ビープ音を扱ってみたとき、音の変化と同様に音量の変化を感じた(プログラム内外で音量を変えたつもりはない)のですが、それもこういうのが関係しているのでしょうか?
音楽ソフトのテンポは、また別の話でピッチシフトまで必要な場合はあんまりないんじゃないと思います(音の出る長さを変えるだけ)。サンプラーとかはピッチシフトするのが当たり前ですが。
ビープ音の音量が変わるのはPCの出力エネルギーが一定で、スピーカーの周波数特性と耳の周波数特性が原因です。それぞれに音量が大きく出る&大きく聞こえる周波数があり一様ではありません。
まぁ、音に関しては学校の理科で習うより色々と複雑で音が波だとちゃんと理解していない人も沢山います。共振とか回折とかの話も一般的ではないでしょう。それほど身近ながら知られていないのが音です。

興味があったら、こんなのから読んでみてください。
「JSTバーチャル科学館|音の正体」
http://jvsc.jst.go.jp/find/sound/index.htm
「人間の耳の特性」
http://www.asahi-net.or.jp/~yl1h-nkmr/oto/tokusei.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#50

投稿記事 by かなたん » 13年前

ISLe さんが書きました: なぜ激しいときに抑えられてしまうことになるのでしょう?
フレームレートはそれ以上の更新速度にはしてほしくないという意味でもあります。
これ以上速くても無駄というのは自分で作ったものをテストプレイしていて分かりますよね(あるいは作る前から決めている)。
アクション性の低いパズルゲームあたりは30FPSでも十分過ぎます。
フレームごとの変化量が少ないのなら、60と設定して60出なくてもきちんと対処できていればだいたい問題ないじゃないですか。
でも、フレームごとの変化量が多かった時、思ったような動きをしない可能性はありませんか?
GIFアニメを各コマ1/100sで作成したことがあります。
コマ上の円を8等分する間隔で円の中心から円周までの長さの線が移動するもので、8コマをループさせています。
各コマ1/100sとなると当然コマの切り替えが早く、時計回りに回るように作っていても反時計回りに回っているんじゃないか?と思えるように見えることもあります。
そんなGIFアニメをとある掲示板にアップしたのですが、掲示板の性能のためか何のためか、明らかに各コマ1/100sではなく、もっと遅くなってしまいました。
1コマの時間を延ばすべく線の動きなどを各コマ1/100sの何とか倍の時を考えて作り直そうかとも思いましたが、それではこのGIFアニメで見せたかったものがうまく表現できなくなるのではないか?と思い、投稿はそのままにあきらめました。
もし実際に作りなおしてみて私が思っているようにうまく表現できなかったとしたら、フレームレートが設定しているように出なくて困ったりするのも似たようなものですよね?
(今回の場合試していないのであくまで予想でしかないですけど。)
ISLe さんが書きました:極端な話リフレッシュレートが1000Hzを超えると1フレームあたりの時間が1ミリ秒未満になってしまうので、ミリ秒精度を前提としたプログラムは動かなくなる可能性があります。
1フレームあたり1ミリ秒以下に設定すると、sleepがうまく働かないということですね?
わざと1001に設定してみたら、確かにそんなfpsは出ませんでした。

コード:

OF: OF_VERBOSE: Start setup()
fps:133.866134
fps:457.542458
fps:471.057884
start
fps:465.069860
fps:448.103792
fps:458.541459
fps:474.525475
fps:458.083832
fps:458.541459
fps:450.396825
fps:461.077844
fps:485.514486
OF: OF_VERBOSE: End Application
続行するには何かキーを押してください . . .
確かにこのようだとミリ秒精度を前提としたプログラムはきちんと動いてくれなくなりますね。
ISLe さんが書きました:最終的に全部ミリ秒で管理してうまくいったではないですか。
うまくいかないのは1ミリ秒がどこでも同じ長さだと思っていることが理由です。
今回のプログラムで言うと、
  • 再生されている音楽
  • フレームレート管理下のメインルーチン
  • かなたんさん
が観測する1ミリ秒という時間がそれぞれ違うのです。
そして、かなたんさんは再生されている音楽やフレームレート管理下のメインルーチンの時間軸をその世界の外から観測しているのです。
MFC(など)のSetTimerは1秒1000ミリ秒で設定できますよね。
たとえば500と設定したとき、OnTimerでカウントさせていればそれは(だいたい?)500ミリ秒ごとにカウントされていることになりますよね。
1カウントはSetTimerで設定した値ですよね。
フレームレートを利用すると、フレームごとにカウントしたときはだいたい設定したフレームレートごとにカウントされていることになりますよね。
設定したあるいは実際に計測したフレームレートから1フレーム何ミリ秒であるかを計算することにより、1カウントが何ミリ秒かがわかりますよね。
MFCのようにミリ秒単位などで設定できれば、このような計算を必要とすることなく1カウントは設定した値ですよね。
getPositionは始まりを0、終わりを1としたfloat値を返しますよね。
これは、再生時間が同じでも曲の長さが違えば返ってくる値も違いますよね。
返ってきた値に曲の長さをかけてあげることにより、今何ミリ秒再生されたのかが分かりますよね。
もし返ってくる値がミリ秒単位なら、そんな計算いらないですよね。
それらは計算式さえかければミリ秒単位に変換させることができますが、私は最初からすべてミリ秒で扱えたら管理しやすいかなと。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#51

投稿記事 by ISLe » 13年前

かなたん さんが書きました:GIFアニメを各コマ1/100sで作成したことがあります。
コマ上の円を8等分する間隔で円の中心から円周までの長さの線が移動するもので、8コマをループさせています。
各コマ1/100sとなると当然コマの切り替えが早く、時計回りに回るように作っていても反時計回りに回っているんじゃないか?と思えるように見えることもあります。
なるほど。おっしゃることは分かりました。
テレビで自動車のタイヤが逆に回って見えたりスマホの動画で飛行機のプロペラが奇妙に変形したりするような状況ですね。
残念ながらわたしは商業プログラマなので再生環境を最優先に考えてあらかじめそういう状況にならないように作ります。
少なくともいまのところGIFアニメで1/100秒を再現できないことは容易に予測できるので作りはじめる前にもっと低いフレームレートを提案するでしょう。
かなたん さんが書きました:MFC(など)のSetTimerは1秒1000ミリ秒で設定できますよね。
たとえば500と設定したとき、OnTimerでカウントさせていればそれは(だいたい?)500ミリ秒ごとにカウントされていることになりますよね。
1カウントはSetTimerで設定した値ですよね。
フレームレートを利用すると、フレームごとにカウントしたときはだいたい設定したフレームレートごとにカウントされていることになりますよね。
設定したあるいは実際に計測したフレームレートから1フレーム何ミリ秒であるかを計算することにより、1カウントが何ミリ秒かがわかりますよね。
MFCのようにミリ秒単位などで設定できれば、このような計算を必要とすることなく1カウントは設定した値ですよね。
残念ながらそうなりません。
タイマーの精度が低ければ500と設定しても500ミリ秒ちょうどにはカウントされませんしイベントが遅延すればさらにズレます。
サウンド再生のスレッドとメインプログラムのスレッドの実行速度が一致する保証もありません。
これはプログラムでフレームレートのタイミング計算の実装がマズくて誤差が蓄積していくのとは別の話です。
何度も言ってますけど指定した時間がいつでもどこでも実時間と一致すると考えてはいけません。
かなたん さんが書きました:getPositionは始まりを0、終わりを1としたfloat値を返しますよね。
これは、再生時間が同じでも曲の長さが違えば返ってくる値も違いますよね。
返ってきた値に曲の長さをかけてあげることにより、今何ミリ秒再生されたのかが分かりますよね。
もし返ってくる値がミリ秒単位なら、そんな計算いらないですよね。
それらは計算式さえかければミリ秒単位に変換させることができますが、私は最初からすべてミリ秒で扱えたら管理しやすいかなと。
「再生時間が同じでも曲の長さが違えば返ってくる値も違いますよね」というのが意味不明です。
この文脈で再生時間と曲の長さって同じものではないのでしょうか?
openFrameworksの中の人はかなたんさんがいらないと思っている計算をするほうが便利だと思っているのでしょう。
音程を変えずに再生速度を変えることができなかったら同じ曲でもレベル毎にテンポの違う曲データを用意したりしますよね。
そうしたらはじめから相対位置で管理したほうがnoteテーブルが共通化できて(余分な計算もしなくて)便利だと思いますけど。
noteテーブルを音符を基準にした数値にすることもできますよ。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#52

投稿記事 by かなたん » 13年前

softya(ソフト屋) さんが書きました:openFrameworksの問題は、動作する環境次第で60fpsにするのが難しいこと(30fpsなら多分大丈夫)とopenFrameworks自体のフレームレート管理が適当なことでしょう。
適当でも何とかやっていけるから、適当なままなんでしょうね。
softya(ソフト屋) さんが書きました:あとkinectが動作するまで持っていけるかは技術的なスキルとの兼ね合いです。そこをどう判断するかですね。
そこは自分たちでいろいろな方法を試してがんばっていこうと思っていますが、お互いの環境が違う(OSがVistaと7だったり、、VSが、2010でも無料版と有料版だったり、使えるOpenCVのバージョンが違ったり)こともあり、同じようにできるのだろうかと思っていたり。
softya(ソフト屋) さんが書きました:芸術関係で多く使われるprocessingと互換性が高いと思われるopenFrameworksですのでメインの人の使いこなせる確率が高そうではあります。他(DXライブラリ)でやってもkinectが簡単かは微妙ですが60fpsは出しやすくなると思います。
processingというのもあるんですね。
もしうまくいかないならそういうのを利用することも提案してみようと思います。
softya(ソフト屋) さんが書きました:音楽ソフトのテンポは、また別の話でピッチシフトまで必要な場合はあんまりないんじゃないと思います(音の出る長さを変えるだけ)。サンプラーとかはピッチシフトするのが当たり前ですが。
サンプラーというのは聞いたことないのですが、確かに作曲ソフトでは各音を鳴らす長さを変えるだけでできますね。
そしたらピッチシフトなどは必要ないですね。
softya(ソフト屋) さんが書きました:ビープ音の音量が変わるのはPCの出力エネルギーが一定で、スピーカーの周波数特性と耳の周波数特性が原因です。それぞれに音量が大きく出る&大きく聞こえる周波数があり一様ではありません。
まぁ、音に関しては学校の理科で習うより色々と複雑で音が波だとちゃんと理解していない人も沢山います。共振とか回折とかの話も一般的ではないでしょう。それほど身近ながら知られていないのが音です。
スピーカーや耳によってビープ音の周波数によって音が大きく聞こえたり小さく聞こえたりするのですね。
本気で興味があるわけではないですが、紹介してくれたサイトも是非見てみようと思います。
ISLe さんが書きました:残念ながらわたしは商業プログラマなので再生環境を最優先に考えてあらかじめそういう状況にならないように作ります。
私は少なくとも自分の環境できちんと動けばいいと思っていて、ちきんとは動かないときにどうしたらいいか悩む人です。
(この考えは商業などの一般公開向けには向いていないですね・・・)
ISLe さんが書きました:GIFアニメで1/100秒を再現できないことは容易に予測できる
そうだったんですね。
少なくとも私が使用しているGIFアニメ作成用ソフト(giam)上では1/100秒で作れても、GIF形式で保存した時点でその精度はないと。
それでも設定できるのは・・・1/100秒はできなくても、ある程度大きいとピッタリにはならなくてもそれなりに合わせてくれるとか?
ISLe さんが書きました:作りはじめる前にもっと低いフレームレートを提案するでしょう。
その精度は今のままではどうしてもできるわけがないので、どうにかしてでもフレームレートを下げてそれでも再現できるように工夫してみるしかないということなのですね。
ISLe さんが書きました:タイマーの精度が低ければ500と設定しても500ミリ秒ちょうどにはカウントされませんしイベントが遅延すればさらにズレます。
サウンド再生のスレッドとメインプログラムのスレッドの実行速度が一致する保証もありません。
これはプログラムでフレームレートのタイミング計算の実装がマズくて誤差が蓄積していくのとは別の話です。
何度も言ってますけど指定した時間がいつでもどこでも実時間と一致すると考えてはいけません。
今回のと同じプログラムを、以前Scratchで作っていたことがあります。
ScratchにはMFCのようなタイマー関数やopenFrameworksのようなフレームレートなどはない(少なくともプログラミングしていて設定する部分がない)です。
それっぽいのであるといえば、起動してから今までどれくらいたったのかのタイマー(秒(小数点3桁まで)単位)くらい?
相対時間待って太鼓を流すタイミングになったら指定の位置に太鼓を配置し、そこから指定時間(秒(小数可 たぶん小数点3桁まで?)単位)内に指定位置まで移動するようにしています。
まだ未完成なこともあり、ちょっと流れてくる太鼓間違えてるなって言うのはあったりするのですが、今プレイしてみても今回のような遅延は発生していないように思います。
でも、キーイベントがうまくはいらない―ドレミの歌の8分音符連続部分などで太鼓もそのように流れてくるのですが、そのように対応させたキーを押してもとびとびにしか反応しなかったので、完成まではあきらめました。
openFrameworksではうまくいきませんでしたが、このようにScratchでは時間同期による音と太鼓の同期はうまくいっていました。
これは、たまたまというかなんというか、このプログラムではScratchで少なくとも私が気付くほどのの音の遅延や太鼓の遅延が発生しなかっただけでしょうか?
openFrameworksのようにすべてがScratchのようにはうまくいかないのでしょうが、私にとってはこのように時間で管理できる方がいいと思っています。
ISLe さんが書きました: 「再生時間が同じでも曲の長さが違えば返ってくる値も違いますよね」というのが意味不明です。
この文脈で再生時間と曲の長さって同じものではないのでしょうか?
たとえば曲の長さ1分のAと曲の長さ2分のBがあったとき、もし再生位置は同じ30秒だとしても、getPositionはAでは1/2000、Bでは1/4000とことなる値を返しますよね?
そういうことを言いたくて書いたのですが・・・私の書き方がよくなくてうまく伝わらなかったようで。
ISLe さんが書きました:openFrameworksの中の人はかなたんさんがいらないと思っている計算をするほうが便利だと思っているのでしょう。
音程を変えずに再生速度を変えることができなかったら同じ曲でもレベル毎にテンポの違う曲データを用意したりしますよね。
そうしたらはじめから相対位置で管理したほうがnoteテーブルが共通化できて(余分な計算もしなくて)便利だと思いますけど。
noteテーブルを音符を基準にした数値にすることもできますよ。
もし曲のテンポに合わせて複数のデータを用意することにすると、曲の長さもそうですし同じ部分でも再生位置が変わってきますが、私はそのときは指定している時間に今のテンポ/元のテンポをかけてやればいいかなと。
でも、openFrameworksの中の人などは、相対位置で管理できた方がnoteの蓄積そのままと比較できていいと思うんですね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#53

投稿記事 by softya(ソフト屋) » 13年前

ちなみにopenFrameworksの実装はC++ですがprocessingの実装はJavaです。
「Extended Language (API) \ Processing.org」
http://processing.org/reference/
processing本体にはサウンドがなくて別のライブラリを組み合わせます。
そういう意味では、openFrameworks用に自分で使いやすいライブラリを作ってやるというのは悪い方法ではないでしょう。
サウンドの再生位置ではなく、サウンドの再生時間を返す事ができるサウンドクラスを追加するのです。
そうすれば、お望みのサウンドの時間での管理になります。

もし絶対的にCPUの時間基準で管理したいのであればサウンドも画像もすべてそちらに同期させる必要が有りますが、それは全てプログラマーの管理で行う必要がありWindowsOSやAPIはそこまでの厳密な時間管理を行なっていませんので理解してくださいね。
時間管理を主体としたOSもあります。逆に言えばRTOSであると明言していないOSは時間管理に限界があると言うことです。
「リアルタイムオペレーティングシステム - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%83%AA% ... 6%E3%83%A0
かなたん さんが書きました:そこは自分たちでいろいろな方法を試してがんばっていこうと思っていますが、お互いの環境が違う(OSがVistaと7だったり、、VSが、2010でも無料版と有料版だったり、使えるOpenCVのバージョンが違ったり)こともあり、同じようにできるのだろうかと思っていたり。
もし出来るだけ多くの人に配布するなら最悪のパターンに合わせる必要性が出てくるでしょう。二人のPCでしか動かさないなら悪い方に合わせるだけでしょう。
OpenCVはバージョン合わせるだけなのでさほどの問題とも思えません。
かなたん さんが書きました:そうだったんですね。
少なくとも私が使用しているGIFアニメ作成用ソフト(giam)上では1/100秒で作れても、GIF形式で保存した時点でその精度はないと。
それでも設定できるのは・・・1/100秒はできなくても、ある程度大きいとピッタリにはならなくてもそれなりに合わせてくれるとか?
根本的な問題として、一般的な液晶モニタのリフレッシュレートが1/60なので1/100で作っても実際問題意味が無いのです。
比率で言えば5コマの内3コマしか表示されません。つまり1/100の精度は必要なかったと思います。
かなたん さんが書きました:もし曲のテンポに合わせて複数のデータを用意することにすると、曲の長さもそうですし同じ部分でも再生位置が変わってきますが、私はそのときは指定している時間に今のテンポ/元のテンポをかけてやればいいかなと。
でも、openFrameworksの中の人などは、相対位置で管理できた方がnoteの蓄積そのままと比較できていいと思うんですね。
かなたんさんが相対位置で管理するライブラリを用意してあげれば解決する問題だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#54

投稿記事 by ISLe » 13年前

かなたん さんが書きました:ScratchにはMFCのようなタイマー関数やopenFrameworksのようなフレームレートなどはない(少なくともプログラミングしていて設定する部分がない)です。
それっぽいのであるといえば、起動してから今までどれくらいたったのかのタイマー(秒(小数点3桁まで)単位)くらい?
相対時間待って太鼓を流すタイミングになったら指定の位置に太鼓を配置し、そこから指定時間(秒(小数可 たぶん小数点3桁まで?)単位)内に指定位置まで移動するようにしています。
まだ未完成なこともあり、ちょっと流れてくる太鼓間違えてるなって言うのはあったりするのですが、今プレイしてみても今回のような遅延は発生していないように思います。
でも、キーイベントがうまくはいらない―ドレミの歌の8分音符連続部分などで太鼓もそのように流れてくるのですが、そのように対応させたキーを押してもとびとびにしか反応しなかったので、完成まではあきらめました。
openFrameworksではうまくいきませんでしたが、このようにScratchでは時間同期による音と太鼓の同期はうまくいっていました。
これは、たまたまというかなんというか、このプログラムではScratchで少なくとも私が気付くほどのの音の遅延や太鼓の遅延が発生しなかっただけでしょうか?
openFrameworksのようにすべてがScratchのようにはうまくいかないのでしょうが、私にとってはこのように時間で管理できる方がいいと思っています。
それは相対時間ではなくて「起動してからの経過時間」という基準に合わせたからですよ。
プログラムの相対速度が違ってもPCのタイマーが唯一絶対の時間軸となっているのです。
500ミリ秒経ったらまた500ミリ秒経つまで待つ、というふうにするとズレが蓄積していきますが、起動してからの経過時間は都度ズレても誤差を蓄積しません。
音楽再生は音楽再生の方で頑張ってPCのタイマーに合わせてくれます。
いまどきのPCなら音楽再生が遅延することはないと思います。保証はありませんが。
またPCのタイマー自体も時計がズレるように絶対ではありませんが結果的にPCのタイマーが持つ時間軸にすりあわされてタイミングが一致するわけです。

連続した時間軸をひとつ選択して唯一絶対とし、それにすり合わせることでタイミングを合わせることができるのです。
今回の質問のプログラムがうまくいったのも音楽の再生時間を基準と決めたからです。
音楽の再生時間が正確だからではありませんよ。
かなたん さんが書きました:たとえば曲の長さ1分のAと曲の長さ2分のBがあったとき、もし再生位置は同じ30秒だとしても、getPositionはAでは1/2000、Bでは1/4000とことなる値を返しますよね?
そういうことを言いたくて書いたのですが・・・私の書き方がよくなくてうまく伝わらなかったようで。
違う曲であれば基準が違うので異なる値を返したところで比較することもなく問題ありませんよね。
BがAを倍の時間で演奏したものなら、Aの30秒の位置はBの60秒の位置ですからどちらも0.5ですし、Bの30秒の位置はAの15秒の位置ですからどちらも0.25です。
太鼓を流すタイミングは間違いなく共有できますよね。
かなたん さんが書きました:もし曲のテンポに合わせて複数のデータを用意することにすると、曲の長さもそうですし同じ部分でも再生位置が変わってきますが、私はそのときは指定している時間に今のテンポ/元のテンポをかけてやればいいかなと。
でも、openFrameworksの中の人などは、相対位置で管理できた方がnoteの蓄積そのままと比較できていいと思うんですね。
相対位置で管理しても同じですよ。
変更があったとき相対位置で管理していると変更箇所が少なくて済むんですよ。

相対位置で作るようにするとそもそも元の曲が出来上がってなくても、楽譜だけで太鼓のデータを打ち込めますし、楽譜(音符の長さの合計)だけでプログラムを作ることができます。
分業が可能になります。
ひとりで作業するとしても工程順に縛られないので効率を上げる余地が広がります。
元の曲に合わせるというのは元の曲が出来上がるまで他の作業が出来なくなるということです。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#55

投稿記事 by かなたん » 13年前

返信が遅れました・・・
softya(ソフト屋) さんが書きました:ちなみにopenFrameworksの実装はC++ですがprocessingの実装はJavaです。
processingはJavaなんですね。
openFrameworksで作ったブロック崩しをprocessingに移植させてみたのですが、似ている部分が多くて思っていたより簡単にできました。

processingってデフォルトでフレームレート60に設定されてるんですね。
(processingでもたぶんそのままでは60ちょうどではないんだろうけど。)
softya(ソフト屋) さんが書きました:processing本体にはサウンドがなくて別のライブラリを組み合わせます。
そういう意味では、openFrameworks用に自分で使いやすいライブラリを作ってやるというのは悪い方法ではないでしょう。
サウンドの再生位置ではなく、サウンドの再生時間を返す事ができるサウンドクラスを追加するのです。
そうすれば、お望みのサウンドの時間での管理になります。
[hr]
かなたんさんが相対位置で管理するライブラリを用意してあげれば解決する問題だと思います。
ライブラリを作ったことはないですが、そういうことができれば自分が作りやすいようにすることができますね。
softya(ソフト屋) さんが書きました:もし絶対的にCPUの時間基準で管理したいのであればサウンドも画像もすべてそちらに同期させる必要が有りますが、それは全てプログラマーの管理で行う必要がありWindowsOSやAPIはそこまでの厳密な時間管理を行なっていませんので理解してくださいね。
時間管理を主体としたOSもあります。逆に言えばRTOSであると明言していないOSは時間管理に限界があると言うことです。
きっちり現実などのミリ秒と同じでなくても、自分でプログラムを組む時にすべてミリ秒単位で表記できたらいいなと言うだけで。
もしSetTimerで500ミリ秒に設定していてもOnTimer正確には500ミリ秒ごとに呼ばれているわけではないとしても、それに自分が気が付いていなければそれでいいかな。とか。
でも、曲とかを使うとSetTimerなどとずれてくる可能性もあるので・・・
とりあえず、プログラム内共通で頼れるミリ秒があればいいんですけどね。
複雑になると面倒なので、ないならないであるものでどうにかするしかないですけど。
softya(ソフト屋) さんが書きました:もし出来るだけ多くの人に配布するなら最悪のパターンに合わせる必要性が出てくるでしょう。二人のPCでしか動かさないなら悪い方に合わせるだけでしょう。
OpenCVはバージョン合わせるだけなのでさほどの問題とも思えません。
今回は知り合いのVistaで動けばいいので、そのパソコンで動くものを作っていこうと思います。
OpenCVは最初一緒に最新版を入れたのですが、Vistaのせいかほかの環境のせいか、私の7での環境でサンプルが動いても知り合いのVistaの環境では~.dll(名前は忘れました)が見つかりませんとか言われてサンプルが動きませんでした。
そこで、知り合いのほうは古いOpenCVを入れてみたところ、サンプルをきちんと動かすことができました。
softya(ソフト屋) さんが書きました:根本的な問題として、一般的な液晶モニタのリフレッシュレートが1/60なので1/100で作っても実際問題意味が無いのです。
比率で言えば5コマの内3コマしか表示されません。つまり1/100の精度は必要なかったと思います。
ソフトで作っている間も、実は設定した通りではなかったのでしょうか?
ISLe さんが書きました:それは相対時間ではなくて「起動してからの経過時間」という基準に合わせたからですよ。
プログラムの相対速度が違ってもPCのタイマーが唯一絶対の時間軸となっているのです。
500ミリ秒経ったらまた500ミリ秒経つまで待つ、というふうにするとズレが蓄積していきますが、起動してからの経過時間は都度ズレても誤差を蓄積しません。
音楽再生は音楽再生の方で頑張ってPCのタイマーに合わせてくれます。
いまどきのPCなら音楽再生が遅延することはないと思います。保証はありませんが。
またPCのタイマー自体も時計がズレるように絶対ではありませんが結果的にPCのタイマーが持つ時間軸にすりあわされてタイミングが一致するわけです。
前述のようにScratchで「起動してからの経過時間」を調べることは容易ですが、そのプログラムでは利用していません。
たとえば、
[hr]
[[ドン]を送る] ドンの太鼓を流すための関数呼び出し
[(1.5)秒待つ] wait
[[ドン]を送る]
[(0.5)秒待つ]
[hr]
のようにして太鼓を流すようにしています。
曲もただ流すだけで、今どこらへんかと言うのは利用していません。というかScratchではできません。
もしタイマーと曲の間などで誤差があるなら、このようにしていては誤差が生じますよね?
ということは、Scratchでは待つにしても曲を流すことにしてもスプライト(画像)を移動させることにしても、すべて私の思っているように動いてくれているということですよね?
ISLe さんが書きました:連続した時間軸をひとつ選択して唯一絶対とし、それにすり合わせることでタイミングを合わせることができるのです。
今回の質問のプログラムがうまくいったのも音楽の再生時間を基準と決めたからです。
音楽の再生時間が正確だからではありませんよ。
はい。
今曲がどの辺まで行っているのかを利用することによって、太鼓と曲をきちんと同期できるようになったんですよね。
これなら、もしも曲が作ったテンポより遅れてしまってもきちんと同期されることができると。
ISLe さんが書きました:違う曲であれば基準が違うので異なる値を返したところで比較することもなく問題ありませんよね。
BがAを倍の時間で演奏したものなら、Aの30秒の位置はBの60秒の位置ですからどちらも0.5ですし、Bの30秒の位置はAの15秒の位置ですからどちらも0.25です。
太鼓を流すタイミングは間違いなく共有できますよね。
もし曲の流れや長さにかかわらず再生してから一定時間(単位は秒またはミリ秒)経ったら処理を行いたい場合は、全体のどれくらい(割合)より初めからどれくらい(秒またはミリ秒)のほうが便利ですよね。
(太鼓の達人ではこのようなことはしたりしないでしょうけど。)
確かに同じ曲でテンポを変えただけなら、相対も便利ですけど。
ISLe さんが書きました:相対位置で管理しても同じですよ。
変更があったとき相対位置で管理していると変更箇所が少なくて済むんですよ。

相対位置で作るようにするとそもそも元の曲が出来上がってなくても、楽譜だけで太鼓のデータを打ち込めますし、楽譜(音符の長さの合計)だけでプログラムを作ることができます。
分業が可能になります。
ひとりで作業するとしても工程順に縛られないので効率を上げる余地が広がります。
元の曲に合わせるというのは元の曲が出来上がるまで他の作業が出来なくなるということです。
私が作るときは曲をあらかじめ作ってからプログラムを作りますが、他人と共同でとなると必ずしもプログラムを作る前に曲ができているとは限りませんね。
曲は決まっていてもテンポが決まっていない時は、音の配置だけは確定しているでしょうから、相対で作っておけば大体変更いらないでしょうね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#56

投稿記事 by softya(ソフト屋) » 13年前

かなたん さんが書きました:ソフトで作っている間も、実は設定した通りではなかったのでしょうか?
間違いなく液晶のリフレッシュレートは超えられません。なので、設定した通りのものが見えていなかったでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#57

投稿記事 by ISLe » 13年前

かなたん さんが書きました:もし曲の流れや長さにかかわらず再生してから一定時間(単位は秒またはミリ秒)経ったら処理を行いたい場合は、全体のどれくらい(割合)より初めからどれくらい(秒またはミリ秒)のほうが便利ですよね。
あらかじめ曲ありき且つデータテーブルを作成した後にいっさい曲を変更しないという前提でも、手間は同じだと思います。
盛り上げるためにサビを増やすとか収録時間の都合でカットとか曲を変更する可能性は多分にあります。
「初めからどれくらい(秒またはミリ秒)のほうが便利」と感じることはまったくないですね。

そもそもデータテーブルがミリ秒単位かどうか気になるのがおかしいですよね。
テータテーブルの中身を直接触るのは非効率です。
楽譜データから変換できないのでしょうか。
楽譜が手書きだったりライブ音源だったりするのでしょうか。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#58

投稿記事 by かなたん » 13年前

softya(ソフト屋) さんが書きました:間違いなく液晶のリフレッシュレートは超えられません。なので、設定した通りのものが見えていなかったでしょう。
指定の速さで動くようコマを調整したら思ったように見えなくなるかもしれないとか思っていましたが、別にその時見えているのがすでにコマ落ちしている(?)から、コマを調整してもたぶん問題なかったのですね。
ISLe さんが書きました:あらかじめ曲ありき且つデータテーブルを作成した後にいっさい曲を変更しないという前提でも、手間は同じだと思います。
盛り上げるためにサビを増やすとか収録時間の都合でカットとか曲を変更する可能性は多分にあります。
「初めからどれくらい(秒またはミリ秒)のほうが便利」と感じることはまったくないですね。
曲の再生位置に関しては、どんなときでも初めからよりも全体のどれくらいの方がいいのですね。
たとえば、
2分の5秒目は1/24、後ろ一分ごっそりカットすると1分の5秒目になって1/12。
と値変わりますよね。
こんなことするかどうか―ですが、こんなときでも割合の方が便利ですか?
割合の値が変わっても曲の長さかけてやれば同じ値になるから、別に困ることないのか・・・
ISLe さんが書きました:そもそもデータテーブルがミリ秒単位かどうか気になるのがおかしいですよね。
テータテーブルの中身を直接触るのは非効率です。
楽譜データから変換できないのでしょうか。
楽譜が手書きだったりライブ音源だったりするのでしょうか。
音源は作曲ソフトで作ったものを利用しています。
noteの値は、最初はテンポやフレームレートを頼りに決めました。
ドレミの歌は♪=120だから2拍で1秒。
1秒で60フレーム表示されるはずだから、付点四分音符だと45フレーム。
のように。
最初は差分を書いていて、後で差分でなく最初からの合計を書いた方が判定するときにいいんじゃないかとも思ったけど、その時は別にその差分を利用できるようにすればいいやでやってました。
(結局フレームレートは当てにならずにうまくいきませんでしたが。)
で、時間同期等でやるとなったときには、フレーム単位だったのを全てミリ秒単位に変換させました。
元を変えずともその数を変換してやればそのまま使えるでしょうけど、私はこのほうがいいと思って元を書き換えました。
もしこの後別単位でやるとなったときは、私はさらにその別単位に直すでしょう。
そのほうが、私にとっては作っていて使っていてわかりやすいんですよ。
出来るだけ値そのまま使えますし。
でも自分が一番見てわかりやすい値にしておいて必要に応じて計算して使うほうが、デバッグなどの時にわかりやすいだろうか・・・?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#59

投稿記事 by softya(ソフト屋) » 13年前

人間が分かりやすい値とコンピューターで処理しやすい値は別だと考えてもらった方が良いでしょう。
なのでプログラム開始時に内部で処理しやす形に一度変換してやれば良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#60

投稿記事 by ISLe » 13年前

かなたん さんが書きました:音源は作曲ソフトで作ったものを利用しています。
noteの値は、最初はテンポやフレームレートを頼りに決めました。
ドレミの歌は♪=120だから2拍で1秒。
1秒で60フレーム表示されるはずだから、付点四分音符だと45フレーム。
のように。
最初は差分を書いていて、後で差分でなく最初からの合計を書いた方が判定するときにいいんじゃないかとも思ったけど、その時は別にその差分を利用できるようにすればいいやでやってました。
(結局フレームレートは当てにならずにうまくいきませんでしたが。)
で、時間同期等でやるとなったときには、フレーム単位だったのを全てミリ秒単位に変換させました。
元を変えずともその数を変換してやればそのまま使えるでしょうけど、私はこのほうがいいと思って元を書き換えました。
もしこの後別単位でやるとなったときは、私はさらにその別単位に直すでしょう。
そのほうが、私にとっては作っていて使っていてわかりやすいんですよ。
出来るだけ値そのまま使えますし。
でも自分が一番見てわかりやすい値にしておいて必要に応じて計算して使うほうが、デバッグなどの時にわかりやすいだろうか・・・?
そういうことならかなたんさんのやりやすいようにするのがいちばんかもしれないですね。

わたしはデータテーブルの中身を見ないので分かりやすいかどうか気にすることもないんです。
どうやらデータテーブルがおかしいとなればデータテーブルを作成するプログラムをデバッグします。

かなたん

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#61

投稿記事 by かなたん » 13年前

softya(ソフト屋) さんが書きました:人間が分かりやすい値とコンピューターで処理しやすい値は別だと考えてもらった方が良いでしょう。
なのでプログラム開始時に内部で処理しやす形に一度変換してやれば良いと思います。
ISLe さんが書きました: そういうことならかなたんさんのやりやすいようにするのがいちばんかもしれないですね。

わたしはデータテーブルの中身を見ないので分かりやすいかどうか気にすることもないんです。
どうやらデータテーブルがおかしいとなればデータテーブルを作成するプログラムをデバッグします。
今回は最終的にうまくいきましたが、うまくいくまでにデータテーブルの値と比較させたい値とを比較するタイミングで出力させるなどして確認したりもしました。
音と太鼓がうまく合わないとなるとそうやって関係ありそうな値を出力させておいて、どちらが間違っているのかをチェックしたりしました。
だんだんうまく合わないなら後者の値を確認して、急にうまく合わなくなれば前者の値を確認しました。
今回に限らず、変数を使っていてうまくいかなければ、配列でもそうでなくても怪しげな変数の値をチェックします。
人間が分かりやすい値とコンピューターで処理しやすい値は別だというのはいろいろとやっていてわかりました。
自作関数などのでは自分の思った通りにできますが、既に用意されているものだと必ずしも自分の思っているそのままに使えるとは限らないですもんね。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: openFrameworks プログラムで曲を流すと、他の処理が遅くなる。

#62

投稿記事 by ISLe » 13年前

かなたん さんが書きました:音と太鼓がうまく合わないとなるとそうやって関係ありそうな値を出力させておいて、どちらが間違っているのかをチェックしたりしました。
だんだんうまく合わないなら後者の値を確認して、急にうまく合わなくなれば前者の値を確認しました。
今回に限らず、変数を使っていてうまくいかなければ、配列でもそうでなくても怪しげな変数の値をチェックします。
間違っているかどうかわからないものを2つ以上掛け合わせたら、正しいかどうかも分からなくなってしまいますから、運任せになりますよ?
正しく動いているように見えても、間違った同士の結果が偶然そう見えるだけかもしれません。
いままでのやり取りからするとそれで良いのかもしれませんが。
完成させるより試行錯誤している方が楽しいこともありますしね。

確実にひとつずつ潰さないと効率以前の問題です。
例えばデータテーブルを使わずに、1拍毎に1個太鼓を出すコード(ほんの1行程度)を埋め込んで、曲とテンポが合うかどうかでプログラムのタイミングのとり方に問題があるかどうか明確になります。
結果を見て分かりやすい楽譜を用意すればデータテーブルのチェックも楽になります。
かなたん さんが書きました:人間が分かりやすい値とコンピューターで処理しやすい値は別だというのはいろいろとやっていてわかりました。
分かってないように感じますね。
人間が分かりやすいとコンピューターで処理しにくい、人間が分かりにくいとコンピューターで処理しやすい、と思っていませんか?
それは直接比較したらの話であって、直接比較しなければ良いのです。
人間が見たり触ったりするところだけ、人間にとって分かりやすくなっていれば良いのです。
そしてあちこち人間が見たり触ったりするのは非効率なことです。
かなたん さんが書きました:自作関数などのでは自分の思った通りにできますが、既に用意されているものだと必ずしも自分の思っているそのままに使えるとは限らないですもんね。
これまでのやり取りで、「コンピュータの世界で自分の思っているように使えるものは何一つ無い」ということは伝わりませんでしたかね。

閉鎖

“C言語何でも質問掲示板” へ戻る