Vista/7 での画面表示2010年02月13日 12:51

どうも Vista/7 では RH1FFT の表示がカクカクすると思っていたら、こんな情報がありました。
 Vistaでは排他の獲得順序が要求順序となることが保証されない
 http://nekojiru.blog.so-net.ne.jp/2007-09-26

単に OS のタイマーの精度の問題かと思っていたのですが、もしかしたら違うかもしれません。
可能性として、描画スレッドが排他オブジェクトをなかなか獲得できずに待たされているというのは、ありえなくはないです。
もし可能であれば、修正してみます。

VC++ /arch コンパイラオプション (SSE2 の使用)2010年01月09日 02:50

プログラマ向けです。

VC++ には /arch コンパイラオプションがあります。
 http://msdn.microsoft.com/ja-jp/library/7t5yh4fd(VS.80).aspx

これは、SSE/SSE2 を使用するかどうかを指定するものです。
SSE/SSE2 を使用するように指定した場合、SSE/SSE2 が使えない CPU では動作しなくなります。
デフォルトでは off になっており、RH1FFT (x86) でも基本的に指定していません。

このオプションを on にしても、自動で SIMD 計算してくれるようになるわけではないと思います(調べたわけではありませんが)。
ただ、FFT 計算部分で SSE2 を on にしてみたところ、かなり速くなることが分かりました(~二倍くらい?)。
そこで、FFT 計算部分のみ、SSE2 が使用できる環境では /arch:SSE2 でコンパイルしたコードを呼び出すようにしました。

SSE2 が使用できるかどうかは、CPUID 命令で取得できます。そのあたりは "SSE2" "CPUID" などで調べてみてください。
 http://ja.wikipedia.org/wiki/Streaming_SIMD_Extensions
によると、SSE2 は Pentium 4 で導入されたようです。
 http://ja.wikipedia.org/wiki/Pentium_4
を見ると、時期的には 2000 年以降に購入した PC では、ほぼ確実に使用できるということですね。

ところでこの /arch オプションは、x64 ビルドでは使用できません。
x64 環境では必ず SSE2 が使用できるので、off にする必要がないためです。
32 bit が 64 bit になったところで実行速度が速くなるわけではないのですが、こういう恩恵はありそうです。

ちなみに SSE2 の使用は、次バージョンのソノグラフ描画の高速化
 http://cessna373.asablo.jp/blog/2009/11/08/4684069
にも、ほんの少しだけ寄与していると思います。

PC で出力中の音を録音する方法22009年12月09日 02:20

PC で出力中の音を録音する方法
 http://cessna373.asablo.jp/blog/2009/12/05/4742710
の続きです。

サウンドカードでサポートしていても、VISTA では PC メーカーの要望で無効にされていることもあるようです。これはひどい。Sony...
このスレッドには、この件について他にもいろいろ情報があります。
http://social.msdn.microsoft.com/Forums/en/windowspro-audiodevelopment/thread/e725bb7c-607c-410a-a495-9c92987a34c4

PC で出力中の音の録音は、Loopback Recording と呼ばれているようです。
VISTA では、標準 API の WASAPI で Loopback Recording ができるようですね。
http://msdn.microsoft.com/en-us/library/ms679146%28VS.85%29.aspx

WASAPI を使用すると、再生の音質もよくなるようです。
そのうち対応するかもしれません。
今はまだメイン開発マシンが XP なので、見送りです。

デバイスドライバも少し調べてみましたが、とりあえず断念。
そのとき見つけたサイトを紹介しておきます。
http://www.wdmaudiodev.com/

画面描画の高速化2009年11月08日 22:08

プログラマ向けです。

ソノグラフ描画の高速化
 http://cessna373.asablo.jp/blog/2009/11/08/4684069
の内容をちょっと書いてみます。

まず、これまでバックグラウンドバッファとして DDB に SetPixel() していたのを、DIB section を作成してメモリ書き込みをするようにしました。
GDI+ とか Dirext 3D/2D とか使わないとだめかなあ、と思っていたのですが、とりあえずこれだけで十分な効果はありました。
とにかく画面いっぱいに SetPixel() するのは止めましょう。って、こんなの常識だったか。
16 bit (High Color) でも 32 bit (True Color) でも速くなりましたが、さすがに 256 色は対象外とさせていただきます :-)
関連する面白そうな話はありますが、まあそこまで突き詰めることはないかな。
 http://www.sun-inet.or.jp/~yaneurao/intensive/diw1.html
 http://lamoo.s53.xrea.com/develop/gdiplus/gdiplus_blt.html

もう一つ、ソノグラフを描画するには、多くの小さいデータに対して FFT を行う必要がありますが、これをマルチスレッド化しました。
こちらはマルチコア/マルチプロセッサ環境でのみ有効になります。
ただ CPU パワーを使いきるのは難しいです。コア 2 個だけでも使い切れないのではないでしょうか。

マルチスレッド化ですが、お手軽にやるなら以下のようなものを使うといいかもしれません。
 Intel Thread Buillding Blocks http://www.threadingbuildingblocks.org/
 OpenMP http://openmp.org/
一応 TBB は試してみて効果はあったのですが、フリー版のライセンスを見たら GPL で断念。まあ LGPL でも使ったかどうかは微妙です。
OpenMP の方は VC++ の標準機能として使えますが、
  http://msdn.microsoft.com/ja-jp/library/tt15eb9t(VS.80).aspx
別途 DLL が必要になるようだし、頑張って使うほどでもないか、という感じです。

結局、自分でそれっぽいのを作成しました。
変なバグが入っていないか心配することにはなりますが、機能を限定している分シンプルだし、中で何をやっているか分かるのはやっぱり安心です。

64 bit プログラミングの注意点2009年11月01日 19:11

プログラマ向けです。

注意点というかなんというか、64 bit 版が
 http://cessna373.asablo.jp/blog/2008/09/28/3787188
でうまく動かなかった理由です。

一言で言えば、「VC++ で、/fp:fast オプション付きでビルドした x64 プログラムは、qNaN と通常の数値を == で比較すると、true になる」ということです。
仕様なのかバグなのか不定動作なのかは分かりません。
ちなみに x86 では fcomp, x64 では ucomisd で比較されているようです。
/fp オプションの意味は、以下のような感じです。
 http://msdn.microsoft.com/ja-jp/library/e7s85ffb(VS.80).aspx

まあ、qNaN を通常処理で使わなければいいだけの話ですが。
実際、そのように修正して、見た目正しく動くようにはなりました。

互換モードに関係なく、Vista で Windows バージョンを取得する方法2009年10月31日 05:06

プログラマ向けです。

Vista 系では、exe ファイルのプロパティの [互換性]-[互換モード] が設定されていると、「本当に動いている OS のバージョン」が取得できません。
しかし
 http://cessna373.asablo.jp/blog/2009/10/31/4664389
の例のように、互換モードの設定とは関係なく「本当に動いている OS のバージョン」を取得したいこともあります。

そういうときは、少し裏技ですが、kernel32.dll 等のファイルバージョンを調べるという方法が使えます。
ファイルのバージョンは、GetFileVersionInfo() API で取得することができます。
これはほとんど OS のバージョンに対応していて、たとえば Vista では 6.0.X.X となっています。
当然無保証ですが、多分大丈夫なんじゃないかな、、、

まあ、本当はバージョンに依存しないプログラムを書くのが一番なのですが。
ちなみに RH1FFT では、再生・録音ボリューム機能の制御にはこの技は使いませんが、他のちょっとしたところで使う予定です。

64 ビット対応2008年07月27日 22:25

 『64 ビット版 RH1FFT』
 http://cessna373.asablo.jp/blog/2008/07/27/3654881
に関連するプログラミングの話です。

64 ビット対応は、必要に応じて INT や DWORD を INT_PTR や DWORD_PTR に置き換えるのが主な作業です。
*_PTR は、64 ビットビルドでは 64 ビット、32 ビットビルドでは 32 ビットの整数としてコンパイルされます。
 『The New Data Types』
 http://msdn.microsoft.com/en-us/library/aa384264(VS.85).aspx
ANSI ビルドと UNICODE ビルド両用の TCHAR みたいなものです。

INT_PTR を INT に代入していたりすると、32 ビットでは問題ないのですが、64 ビットでは桁の切捨てが発生するので問題になることがあります。
それを 32 ビットビルドで検出するために、VisualStudio 2005 には /Wp64 (64 ビット移植性の問題の検出) オプションがあるのですが…これがいまいちです。
まず INT& 引数に INT_PTR を渡しても、INT_PTR& 引数に INT を渡しても、警告が出ません。ちょっとひどすぎますね。

さらに template <typename INT_PTR> と template <typename INT> が同じインスタンスになります。
これにより、例えば
 template <typename T>
 T Max(T lhs, T rhs)
 {
  return lhs < rhs ? rhs : lhs;
 }
のような良くあるテンプレートを定義していると、
 int main()
 {
  INT_PTR i = 0, j = 0;
  INT_PTR k = Max(i, j); // INT_PTR Max(INT_PTR, INT_PTR) のインスタンスが生成される。

  INT i2 = 0, j2 = 0;
  INT k2 = Max(i, j);  // INT_PTR Max(INT_PTR, INT_PTR) が使われる。戻り値の INT_PTR を INT に代入しているので警告。

  return 0;
 }
となったり、
 int main()
 {
  INT i = 0, j = 0;
  INT k = Max(i, j);    // INT Max(INT, INT) のインスタンスが生成される。

  INT_PTR i2 = 0, j2 = 0;
  INT_PTR k2 = Max(i, j);  // INT Max(INT, INT) が使われる。引数で INT_PTR を INT に代入しているので警告。

  return 0;
 }
となったりで、無意味な警告のオンパレードです。しかも使用する順番によって内容が変わります。

さんざん試行錯誤した末、/Wp64 オプションを使うのは止めて、単に x64 プラットフォーム用にクロスコンパイルしました。
 『方法 : Visual C++ プロジェクトを 64 ビット プラットフォーム用に設定する』
 http://msdn.microsoft.com/ja-jp/library/9yb4317s(VS.80).aspx
その結果、手許の環境では実行できない 64 ビット版ができあがったというわけです。
VisualStudio 2008 ではひょっとしたら改善されているかもしれませんが、やはり一番いいのは /Wp64 なんか使わずに、素直に 64 ビットでビルドしてみることですね。

Visual Studio 2008 ワンポイント2008年05月25日 01:00

既存情報の紹介をやり出すと、怠け癖が付きそうですが…
「Visual Studio 2008 ワンポイント」のブログです。
 http://blogs.msdn.com/vstipsjpn/

RH1FFT でも、こういう情報をもっと出せればいいのですが。

Visual C++ 2008 Feature Pack2008年05月25日 00:59

現在 RH1FFT は、Visual Studio 2005 で MFC を使用して C++ で作成しています。
見て分かるとおり、ダイアログ形式のプログラムで、本格的なドキュメントビュー形式のものではありません。

最初はとりあえず簡単にと思って作ったものを引きずっていて、そのせいで苦労することもあります。
しかし MFC の SDI/MDI プログラムは見た目が古臭いし、がんばって移行することもないかなと思っています。

…と思っていました。
が、Visual Studio 2008 では Feature Pack なるものがあって、MFC でも最近っぽい GUI が作れるようです。
まだ日本語版では使えないようですが。
 http://msdn.microsoft.com/ja-jp/magazine/cc507634.aspx

一応 Visual Studio 2008 は入手しているのですが、まだしばらく使うことはないと思います。
サブマシンの Windows 2000 でもビルドできるようにしておきたいので。
(Visual Studio 2008 は Windows 2000 では動きません)

WM_NCHITTEST2008年05月18日 21:23

プログラマ向けの話題です。

背景をドラッグしてダイアログを移動する機能について書きましたが、
 http://cessna373.asablo.jp/blog/2008/05/11/3500439
それを簡単に実現する方法です。

特に特別なことはなくて、WM_NCHITTEST で HTCAPTION を返すだけです。
詳しくは、WM_NCHITTEST と HTCAPTION で検索すればいろいろ出てきます。

簡単に言うと、マウスイベントが発生したとき、以下のような処理になっているということです。
 1. ウィンドウマネージャがウィンドウに WM_NCHITTEST を送る。
 2. ウィンドウはマウス位置に応じて、そこがキャプションか、クライアント領域か、などの情報を返す。
 3. クライアント領域でなければ、ウィンドウマネージャはウィンドウを移動するなどの独自の処理を行う。クライアント領域なら、単に WM_MOUSE*** メッセージを送る。

単純なダイアログの場合は HTCAPTION を返すだけでいいのですが、プロパティシートのプロパティページなど、ダイアログの子ウィンドウでは HTTRANSPARENT を返すなどの工夫が必要になります。
この辺りはいろいろ試してみてください。

以前、Win2k だとサイズボックス上でマウスカーソルが変わらないという問題について書きました。
 http://cessna373.asablo.jp/blog/2008/01/26/2580943
ここに書いているとおり WM_SETCURSOR でカーソルを設定してもいいのですが、それ以外に WM_NCHITTEST で HTBOTTOMRIGHT を返す方法もあります。