報告A - 「徐々にずれていく」

 Y社製チップを搭載したサウンドカードで 44100Hz のサウンドを 48000Hz で再生すると次第に音がずれていくという珍現象は、サウンドカードの出力はビットパーフェクトであり精度も高く数分ごときで狂うことはないと思い込んでいた自分の固定観念を吹き飛ばしました。

 まぁこれはサウンドデバイスだけで自爆した初期の極端な例であって、現在ではそんな地雷デバイスは見かけないので安心してください。(編注:この記事の執筆から7年経った現在でもまだあります。普通に売られてます。安心してはいけません。)

 ここでは、今なお続く音ズレ二大報告のうちの1つ、「最初のほうは問題なかったのに演奏が進むにつれてBGMと譜面とのズレが徐々に広がっていくというサウンドのズレ」についてお話ししたいと思います。

 ええ。今なお続く、です。

同期しない 2 つのタイマー

 このようなタイプの音ズレは、サウンドデバイスが自前で持っているタイマー(以降、サウンドタイマーと称する)の精度が、微妙にシステムタイマーと異なってしまう場合に生じます。

 基本的に、サウンドタイマーとシステムタイマーの完全な同期は保証されるものではありません。リアルタイム演奏アプリや音ゲーでもない限り、完全に同期させる理由がないからです。そしてもし同期させるとしたら、高品質・高精度にこだわったサウンドタイマーにこそシステムタイマーのほうが合わせるべきだ、とサウンドデバイスメーカーは主張するかも知れません。

 まあそんな深い事情までは分かりませんけど、現実問題として、サウンドタイマーとシステムタイマーは、時間の経過とともにズレていきます。これは、20 年以上経ってもまだ確信している経験則でもあります。

時々刻々と精度が変化していたパフォーマンスカウンタ

 GetTickTime, timeGetTime に続く第三のシステムタイマーとして登場したのが、パフォーマンスカウンタです。その精度は非常に高く、100ns(ナノ秒)単位です。1ms = 1,000μs = 1,000,000nsなので、1ms の 1万分の1の精度になります。

 まぁ 第三といっても、パフォーマンスカウンタ自体は Windows 95 / Windows NT 3.1 の古き時代から導入されているので、それほど新しい機能でもありません。ただ、最近までまともに対応できるハードウェアがなかったので実戦投入が遅れた、と言えます。

 100ns 単位のタイマーを作るには、単純計算でも 1GHz のクロック周波数を安定して発生させるハードウェアが必要になります。ほとんどの場合、それは CPU かマザーボードです。

 現在では対応するハードウェアも増え、精度も上がり、信頼性も十分に高まっているパフォーマンスカウンタですが、ハードウェアの対応が中途半端だった過去の時代には、以下のような、今では笑い話にしかならないおもしろおかしい現象も起きていました。

  • プロセスを担当する CPU コアが変わるたびに、異なったカウンタ値が返された。
  • CPU やマザーボードのクロックを使用している場合、クロックアップを行うとカウンタも巻き添えになって進むのが早くなった。
  • 負荷が少ないときに周波数を下げるよう設計されている CPU のクロックを使用している場合、CPU の負荷が上下するたびカウンタの早さも上下した。

 ……いや、当事は何とかしようと必死だったんですよ?

 DTXMania では、リリース 059(2005/12/09)で初めてパフォーマンスカウンタに対応し、ハードウェアが対応している場合には、GetTickTime や timeGetTime よりも優先的に使用するようにしていました。当時は。

WAVE再生位置自動補正機能(AdjustWaves)

 実態がどうであれ、サウンドタイマーとシステムタイマーが同期しないなら、自分で同期させればいいじゃない。
 そんな想いを実現したのが、DTXMania リリース 027f(2002/01/09)で導入された AdjustWaves オプションです。人呼んでWAVE再生位置自動補正機能

 なんかかっこいいこと言ってますが、この機能は偶然の産物です。

 ディスク故障で失われた DTXMania を(027シリーズとして)新しく作り直していたとき、DTXMania の演奏を一時停止・再開するという機能も追加していました。この機能はすぐに完成するのですが、いざ使用してみると、停止し、再開した時に、それまでズレていた BGM と譜面がぴったり一致するではありませんか! まあその瞬間からまたズレていくんですけどね

 演奏中、一時停止して再開すれば、BGM と譜面のズレがそのたびに何度でも解消されるという挙動が確認できました。

 仕組みはこうです。
 一時停止するとき、DTXMania は、BGM の再生を停止するとともに、その瞬間の時刻(システムタイマーの値)を記憶します。そして、再開する際には、記憶していたシステムタイマーの値からBGMの再生開始位置を計算して、その位置からBGMの再生を再開するようにサウンドデバイスに指示します。

 つまり、再開のたびに、システムタイマーとサウンドタイマーを同期させていたわけですね。

 WAVE再生位置自動補正機能は、この作業(BGM の再生位置の補正)を自動的かつ定期的に行うことで、ズレが小さいうちにシステムタイマーとサウンドタイマーを同期し続けよう、という機能です。具体的には、小節線が判定バーの上に来るタイミングで、総再生時間が 5000㎳ 以上の WAVE サウンド(BGM とか SE とか)に対してこの補正を行うようにしました。

 これで、BGM と譜面が徐々にズレていく問題が当面は解決されました。

 ですが、副作用もありました。

 BGM の再生位置を強制的に移動するため、再生されているサウンドデータがそこで不連続になり、「プツッ」というノイズを発生させてしまいます。このノイズは静かな曲やイントロなどでは顕著に聞こえるので、耳にしたことのある人も多いことと思います。

 加えて、「音ズレの原則」に従えば、この機能が裏目に出てしまうこともあります。
 それは、「徐々にずれていく BGM に合わせて(=WAVE 再生位置自動補正機能を OFF にした状態で)作られてしまった譜面は、この補正機能を使ってもほぼ間違いなくズレる」という副作用です。こうなったら悲惨です。その譜面は、もう二度と音ズレなしに演奏されることはないでしょう。

 今のところ、これらの副作用を確実に回避する手段は見つかっていません。
 と言うより、詳細は後述しますが、今後はこの機能が不要になる方向へと向かいます。