- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-05-10T12:02:49+09:00","","")
#author("2023-05-16T19:37:05+09:00;2023-05-16T19:36:12+09:00","","")
** DirectSound1 [#w29c50a4]
DirectSoundを鳴らすにはタイマーやDMAなどを組み合わせます。
音を鳴らすには様々なハードウェア機能を使い、実現しています。DirectSoundは極地といっても過言ではありません。ここでは非常に面倒ではりますけれど、ガチガチに決まったらルールに従ってコードを追いかける形になります。窮屈ではありますがご容赦ください。さて、まず一番最初の話をしますと音とは何かというところから始めます。
そもそも音とは何か、ということから始めてみます。
まずはわかりやすく考えるために、音のデータから着目してみましょう。~
** 音とは [#zb4e8281]
普段何気なくパソコンで使っている音楽。音楽とはバイナリデータの集まりです。CD音質は1秒間を44100分割されていて、1分割分の音の高さは2バイト、ステレオの2ch再生です。計算すると以下のようになります。
よく音楽CDのリッピングで耳にするwavファイルの~
「44100Hz stereo 16bit」という形式がスタートです。~
44100(Hz) * 2バイト(16bit) * 2(ステレオ)* 1(秒) + 44(ヘッダ) = 176,444バイト
** wavファイルフォーマット [#ucff091f]
手前味噌ですが1秒の無音データをフリーソフトで作ってみました。~
以下、バイナリエディタで表示したものです。~
#ref(1.png,nolink)
#ref(clip_1.png,nolink)
wavファイルの中身はヘッダ部とデータ部に分かれています。ヘッダは0x00-0x43までの44バイト。残りのデータは0x0000で埋まり、ファイルサイズは176,444バイトとなっています。音の高さ2バイト(16bit)の中身は符号付き signed (-32768 ~ +32767, 無音は0)です。
この中身はヘッダ部とデータ部に分かれています。~
ヘッダはカーソルで反転してある44バイト。~
残りのデータは0x00で埋まり、ファイルサイズは176,444バイトとなっています。~
** 440Hzのラ音 [#wf9db66e]
音を人工的に作ってみましょう。以下に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倍あると考えてください。縦軸は音の高さです。
内訳は~
176,444バイト = 44100(Hz) * 2(ステレオ)* 2バイト(16bit) * 1(秒) + 44(ヘッダ)
です。~
#ref(2.png,nolink)
別の言い方をすると1秒を44100個に分割し、ステレオで2倍し、~
2バイト(16bit)単位で音の高さを保存してある、ということが言えます。~
さらに仕様書をつっこんでみると、2バイト(16bit)の中身は~
16bit ならば符号付き signed (-32768 ~ +32767, 無音は 0)
なんて情報もわかりますね。0x00で埋まっているのも納得です。~
次にGBAについてですが、これはGBATEK先生の出番です。~
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(符号付き)となっています。~
** 加工方法 [#q4014486]
サンプルの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側のソースコード [#b0206fc8]
*** 動作画面 [#l222045a]
** 履歴 [#l5bd00ff]
- 2023/05/09
- 2019/01/05