2010-01-05

Windows 7のBeep ドライバってどうなったのさ?

Larry Osterman's WebLog : What’s up with the Beep driver in Windows 7?

今朝早く、ある人が僕に、「なんで64bit版のWindowsは、PCの内部beepスピーカーをサポートしてないんだい」と訊ねてきた。その答えは、すこしばかり複雑なんだ。また、PCを取り巻く環境とも関係していて、なかなか面白い問題だ。

まず、当時[1]のbeepハードウェアが、どのように機能しているかということについて説明するね。元々、IBM PCは、Intel 8254 プログラマブル・インターバル・タイマー・チップを搭載して、システムクロックを作り出していたんだ。IBMのエンジニアは当時、PCは音を鳴らす必要がある(高音質とまではいかないけれど)と考えたから、8254を、矩形波生成器として使うことにした。このために、エンジニア達は、チップの第三タイマーを使って、矩形波モードを操作できるようにし、好きな出力周波数をカウントできるようにしたんだ。このため、Out2ラインは、クロックが0になるたびに、highからlowへとトグルする。ハードウェアの設計者は、チップのOut2ラインをBeepスピーカーにつなげた。するとほーら、クロック・チップを使って、Beepスピーカーにノイズを鳴らすよう、プログラムできるようになったじゃないか(それほど良い音じゃないけど、まあノイズには違いない)

Beep() Win32 APIは、基本的に、この8254 PIC機能の、薄いラッパーに過ぎない。Beep() APIを呼ぶということは、8254をプログラムしてBeepスピーカーから音を鳴らすということなんだ。

25年もの月日は、飛ぶように早く流れた。PC業界は大きく変わり、PCのアーキテクチャも変わっていった。この時点で、もはや8254を、プログラマブルな割り込みコントローラとしては使わなくなってしまったのだけれど、まだまだ新型PCにも搭載されている。というのも、8254は、いまだに現役でBeepスピーカーを操作するのに使われているからなんだ。

他に、25年のうちに起こった出来事といえば、パソコンはもっともっといろんなことができるようになった。今や、パソコンは奇妙で斬新な新型ハード・ディスク・ドライブを搭載しているっていうじゃないか。僕はよく分からないんだけど、中には30メガバイト以上もの容量をもつヤツがあるっていう話じゃないか。(でも、そんな大容量のハードディスクなんて、誰が欲しがるんだろうね。僕には分からないや)。それに、サーバーじゃないパソコンはみんな、サウンドカードを搭載してる。そんなわけで、今売られているパソコンは、音を鳴らす方法が二つある。サウンドカードと、昔ながらの、内部Beepスピーカーにつながってる8254とだ。(あるいは、サウンドカードの専用入力とか、これは後で説明するけど)

この25年のうちに起こったことは、まだまだある。パソコンは家電になった。パソコンメーカーは、厳しいコストカットを余儀なくされることになったんだ。メーカー各社は、8254に目をつけて、言った。「なんでコレを取り除けないんだ?」と。

でも、それは無理な相談だった。なんでかっていうのが、ものすごく期待はずれの変な理由なんだ。障害を持つアメリカ人法(ADA)のせいなのさ。

ADAだって?ADAとパソコンのBeepと、何の関係があるっていうんだい? それがねぇ、この25年間のどこかで、Win32 Beep()は、障害者補助の技術として使われてたらしいんだよ。StickyKeysみたいな、障害者補助技術は、Beep() APIを使って、一連の音を鳴らしていたんだよ。Windowsには、六つの障害者補助技術(AT)音が、組み込まれて、その実装は、win32k.sysの奥深くに入り込んでいるんだ。

でも、なんでそれが問題になるのさ? それがねぇ、多くの業界団体(政府と民間企業の両方)では、障害者補助技術のない製品は買わないっていう決まりがあるらしくて、つまり、メーカー各社は、beepハードウェアがないパソコンを、そういう業界団体に売ることができないってわけなんだ。

この問題に、最初に気がついたのは、マイクロソフトが64bit版のWindowsを開発していたときなんだ。というのも、最初の64bit版Windowsは、サーバー用途だったから、64bit機が想定する環境として、8254のサポートなんてなかったんだ(障害者補助技術の決まりごとは、サーバーに対しては、すこし緩められたらしい)。でも、一般ユーザー向けの64bit OSを開発しだしたら、問題に直面してしまった。一般ユーザー向けのOSは、障害者補助技術をサポートしなければならなかったんだ。そんなわけで、何とかしてbeepをサポートしなくちゃいけなかったんだ。そもそも、beepハードウェアがないパソコンばかりなのにね。

Windows XPでは、winlogonに、ソレ用のコードを書いて、この問題に対処した。一応動いたんだけど、ちょっと複雑だった(この話には直接関係ないけどね)。Windows Vistaでは、僕は設計をやりなおして、障害者補助のbeepの仕組みを、新しい「ユーザー・モード・システム・サウンド・エージェント」に移した。

この問題のあるパソコンというのは、64bit機だけだから、この機能は64bit版Windows限定の話だよ。

これはつまり、パソコンメーカーは、まだまだ8254というハードウェアをサポートし続けなくちゃならないってことなんだ。そもそも、ユーザーが32bit版のOSを買った場合、もしかしたら、障害者補助機能を使いたがるかもしれないからね。

Windows 7では、この問題を完全に解決した。Beep.sysにあった機能もぜんぶ、ユーザー・モード・システム・サウンド・エージェントに移したんだ。これで、Beep() APIを呼んでも、8254チップを操作するかわりに、実際の音を再生するユーザー・モード・エージェントに丸投げできるって寸法さ。

この計画では、思わぬ利点もあったんだ。8254出力ラインは、サウンドカードの専用入力につながってるって、さっき言ったよね? このサウンドカードへの入力のせいで、サウンドハードウェアは、つねにフルパワーで電源供給されてなきゃならないんだ。だって、アプリケーションがいつ、Beepを呼んで、8254を叩くか、分からないからね。(電源管理機構では、8254は操作できないんだ。だから誰かが8254の第三タイマーをプログラムした時だけ、サウンドハードウェアを起こすなんてことはできないんだ)。Beep呼び出しを、システム・オーディオ・ハードウェアにリダイレクトすることで、サウンド・ハードウェアは、必要になるまで、スリープさせておけるようになったんだ。

このリダイレクトで、また思わぬ利点があったんだ。それも複数。たとえば、間違って、0x07文字を含むファイルをtype、あるいはgrepしたとき(たとえば.objファイルとかね)、あのイヤーなノイズを消すことができるようになったんだ。beepはもう、パソコンのスピーカーから再生されているわけだから、パソコンのミュートボタンで、ささっと消すことができるってわけさ。また、beepのボリュームを操作することもできるようになったよ。

また、思いがけない発見もあったよ。一番傑作なのは、アプリケーションがBeep()を使っていたということに、みんな気がついたってことだね。みんな、パソコンをかなり離して置いていたり、あるいは、周りの音が大きすぎたりして、パソコンがbeepを鳴らしていることに、気がつかなかったんだね。それが、いきなり手元のスピーカーから鳴り出したんだからね。

[1] というわけで、僕がいまだに1980年ものの、昔のIntelの部品データ・カタログを捨ててないのは、正しい選択だったってわけさ。

Larry Ostermanは、このブログでも、何度か取り上げているが、Raymond Chenに次ぐ、有名なマイクロソフトの古参プログラマのブロガーである。Raymond Chenほど頻繁ではないが、たまに、Windowsの昔話を疲労してくれる。彼はWindowsのオーディオ周りを担当している。

ちなみに、Larry Osterman本人は、かなりのヒゲモジャなので、この翻訳の文体は、少し見かけに合わないかもしれない。

むかし、16bit DOSからアセンブリで直接8254を叩いて、音を鳴らして遊んでいたのを思い出した。

それにしても、最近は翻訳文が、流れるようにスラスラ出てくるから気持ちがいい。翻訳の仕事でもしたいものだ。

3 comments:

r said...

>Windowsの昔話を疲労してくれる。

言い得て妙ですね

hito said...

直さないでおこうかなw

Anonymous said...

事務所なんかではスピーカーをミュートにしている事が多いです。

なので、BEEP音をスピーカーから出されても、音が聞こえない。

フツーにマザーボード上のスピーカーから音を出して欲しいと思うなぁ。

もちろん、マザーにスピーカーがなきゃダメだけど。