DirectSound1

音を鳴らすには様々なハードウェア機能を使い、実現しています。DirectSoundは極地といっても過言ではありません。ここでは非常に面倒ではりますけれど、ガチガチに決まったらルールに従ってコードを追いかける形になります。窮屈ではありますがご容赦ください。さて、まず一番最初の話をしますと音とは何かというところから始めます。

音とは

普段何気なくパソコンで使っている音楽。音楽とはバイナリデータの集まりです。CD音質は1秒間を44100分割されていて、1分割分の音の高さは2バイト、ステレオの2ch再生です。計算すると以下のようになります。

44100(Hz) * 2バイト(16bit) * 2(ステレオ)* 1(秒) + 44(ヘッダ) = 176,444バイト
1.png

wavファイルの中身はヘッダ部とデータ部に分かれています。ヘッダは0x00-0x43までの44バイト。残りのデータは0x0000で埋まり、ファイルサイズは176,444バイトとなっています。音の高さ2バイト(16bit)の中身は符号付き signed (-32768 ~ +32767, 無音は0)です。

440Hzのラ音

音を人工的に作ってみましょう。以下に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倍あると考えてください。縦軸は音の高さです。

2.png
 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(符号付き)」形式で鳴らす予定なので
ヘッダがない、素のデータのみ、ということがわかると思います。

GBA側のソースコード

動作画面

履歴


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS