DirectSound1

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

音とは

普段何気なく聞いている音楽。その記録媒体の1つCDディスクは、バイナリデータの集まりです。円盤の1秒は44100分割されていて、1分割分の音の高さは2バイトであり、ステレオの2チャンネルで構成されています。これをwavファイルフォーマットに置き換えると以下になります。

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秒間モノラル出力したものです。以下のグラフは横軸0〜441(44100 / 100)。縦軸は繰り返しの説明になりますが、2バイト(16bit)、符号付きsigned(-32768 ~ +32767, 無音は0)です。

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