音を鳴らすには様々なハードウェア機能を使い、実現しています。DirectSoundは極地といっても過言ではありません。ここでは非常に面倒ではりますけれど、ガチガチに決まったらルールに従ってコードを追いかける形になります。窮屈ではありますがご容赦ください。さて、まず一番最初の話をしますと音とは何かというところから始めます。
普段何気なくパソコンで使っている音楽。音楽とはバイナリデータの集まりです。CD音質は1秒間を44100分割されていて、1分割分の音の高さは2バイト、ステレオの2ch再生です。計算すると以下のようになります。
44100(Hz) * 2バイト(16bit) * 2(ステレオ)* 1(秒) + 44(ヘッダ) = 176,444バイト
wavファイルの中身はヘッダ部とデータ部に分かれています。ヘッダは0x00-0x43までの44バイト。残りのデータは0x0000で埋まり、ファイルサイズは176,444バイトとなっています。音の高さ2バイト(16bit)の中身は符号付き signed (-32768 ~ +32767, 無音は0)です。
音を人工的に作ってみましょう。以下にpythonのソースコードを載せますが読まなくて結構です。
import numpy as np import wave import struct from matplotlib import pylab as plt fname = '1sec_440Hz.wav' fs = 44100 f = 440 sec = 1 A = 32767 samples = sec * fs t = np.linspace(0, sec, samples) s = A * np.sin(2 * np.pi * f * t) s = s.astype(np.int16) data = struct.pack("h" * samples , *s) wf = wave.open(fname, 'w') wf.setnchannels(1) wf.setsampwidth(2) wf.setframerate(fs) wf.writeframes(data) wf.close() plt.plot(s[0:441]) plt.show()
このプログラムは440Hzのドレミファでいうラ音を1秒間モノラル出力したものです。音の高さはsin関数を使っています。以下のグラフは44100 / 100分割した横軸で構成されています。このグラフの100倍あると考えてください。縦軸は音の高さです。
The Sample Rate The GBA hardware does internally re-sample all sound output to 32.768kHz (default SOUNDBIAS setting). It'd thus do not make much sense to use higher DMA/Timer rates. Best re-sampling accuracy can be gained by using DMA/Timer rates of 32.768kHz, 16.384kHz, or 8.192kHz (ie. fragments of the physical output rate).
適当翻訳すると「GBAは32.768kHzで音が鳴るんで32.768kHz, 16.384kHz, 8.192kHz」の
どれかにしといた方がいいぜ、とアドバイスしてくれてます。
例でいえば、画像ファイルのアスペクト比を無視して
縮小をするんじゃないぞ、と忠告してもらっているようなものです。
音の中身はモノラルであり、音単位は8bit singed(符号付き)となっています。
サンプルのsrc\res\Makefileの抜粋を見てみましょう。
.wav.s: $(WAVFILES) @echo \# converting $< @./sox $< -r 16384 -c 1 -B -s -1 $*.raw @padbin 4 $*.raw @bin2s $*.raw > $@ @rm $*.raw
データはsox(音フォーマット変換ツール)、padbin(バイト境界調整ツール)、
bin2s(アセンブリテキスト変換ツール)、に掛けていき、GBAのプロジェクトと結合します。
soxのコマンドオプションを詳しく見てみましょう。
soxのコマンドオプションはこのようになっています。
-r RATE sample rate of audio -c CHANNELS number of channels of audio data; e.g. 2 = stereo -B force endianness to big/little -s sample encoding: signed -1 sample size in bytes
コマンドプロンプトで打ち込んだ結果を以下に表します。
> sox 1sec.wav -r 16384 -c 1 -B -s -1 1sec.raw > > dir 1sec.raw > > 2019/01/05 xx:xx 16,384 1sec.raw
0x00で埋まった16,384サイズのファイルが出来上がりました。
GBAは「16384Hz モノラル 8bit(符号付き)」形式で鳴らす予定なので
ヘッダがない、素のデータのみ、ということがわかると思います。