この記事について
音声ファイルの中でも最もシンプルで構造が分かりやすいフォーマットが WAV(Waveform Audio File Format) です。
WAV はその名のとおり 「波形(waveform)」をそのまま保存したファイルであり、複雑な圧縮もありません。
この記事では以下について解説します
- WAV はどのように波形を保存しているのか
- 波形とはそもそも何か
- Python を使って波形を描く
- 波形から WAV を生成して音を鳴らす
1. そもそも音とは?
音とは「空気の振動」です。
スピーカーは膜を前後に震わせ、この震えが空気を押したり引いたりします。
これを時間軸に沿って数値化したものが 波形データ(waveform)です。
2. 波形(waveform)とは?
波形とは「時刻 t における空気の振幅を数値で並べたもの」です。
例えば、440Hz(A/ラの音)は次の正弦波になります。
y(t)=sin(2π⋅440⋅t)

https://www.slp.k.hosei.ac.jp/~itou/intro/sound_intro.html より引用
3. Python で波形を描いてみる
import numpy as np
import matplotlib.pyplot as plt
sr = 44100 # サンプリングレート
freq = 440 # A4 (ラ)
duration = 0.01 # 描画区間(秒)
t = np.linspace(0, duration, int(sr * duration), endpoint=False)
wave = np.sin(2 * np.pi * freq * t)
plt.figure(figsize=(8, 3))
plt.plot(t, wave)
plt.title("440Hz Sine Wave")
")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.grid(True)
plt.show()
実行結果
この波形を拡大すると「スピーカーが前後に振れる量」が見えるわけです。
4. WAV ファイルの仕組み
WAV はとてもシンプルで、内部構造は大きく次の2つだけです。
- ヘッダ(Header):再生方法を説明する情報
- データ部(Data):波形そのものの数値が並ぶ
WAV ヘッダの中身(ざっくり)
| 項目 | 内容 |
|---|---|
| ChunkID | "RIFF" |
| Format | "WAVE" |
| Subchunk1ID | "fmt " |
| AudioFormat | 1 = PCM(非圧縮) |
| NumChannels | 1 = mono, 2 = stereo |
| SampleRate | 44100 など |
| BitsPerSample | 8, 16, 24, 32 bit |
| Subchunk2ID | "data" |
| Subchunk2Size | データサイズ(バイト) |
実際の音データは、このヘッダのあとに 整数の列として並びます。
波形 → WAV の変換とは?
波形は -1.0 〜 +1.0 の浮動小数として扱われることが多いですが、WAV は整数しか保存しません。
例:16bit PCM の場合
整数の範囲は「-32768 〜 +32767」
つまり、浮動小数の波形を 16bit 整数に変換して保存するだけです。
5. Python で波形から WAV を生成して音を鳴らす
以下のコードは4つの項目を行います
- ドレミファソラシドを正弦波で作る
- 波形を描画する
- 正しい WAV として保存する
- 音を再生できる
import numpy as np
import matplotlib.pyplot as plt
import wave
import struct
# サンプリングレート
sr = 44100
# ドレミファソラシド(C4〜C5)
freqs = [
261.63, 293.66, 329.63, 349.23,
392.00, 440.00, 493.88, 523.25
]
note_duration = 0.6
silence = 0.05
t = np.linspace(0, note_duration, int(sr * note_duration), endpoint=False)
def adsr_env(length, sr):
env = np.ones(length)
a = int(sr * 0.01)
r = int(sr * 0.03)
env[:a] = np.linspace(0, 1, a)
env[-r:] = np.linspace(1, 0, r)
return env
scale = np.array([], dtype=np.float32)
for f in freqs:
wave_data = np.sin(2 * np.pi * f * t) * adsr_env(len(t), sr)
scale = np.concatenate([scale, wave_data, np.zeros(int(sr * silence))])
# 正規化して16bit整数へ
scale_int = np.int16(scale / np.max(np.abs(scale)) * 32767)
# WAV 保存
file_path = "scale.wav"
with wave.open(file_path, 'wb') as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(sr)
wf.writeframes(struct.pack('<' + 'h'*len(scale_int), *scale_int))
print("WAV を保存しました:", file_path)
# 波形の一部を描画
plt.figure(figsize=(10, 3))
plt.plot(scale[:3000])
plt.title("波形のズーム(冒頭部分)")
plt.xlabel("Samples")
plt.ylabel("Amplitude")
plt.show()
上記波形のscale.wavファイルも生成されます
6. WAV の本質:波形をそのまま保存したファイル
WAVはシンプルで、この2つだけで構成されます。
- 波形(振幅の数値列)
- そのデータの解釈方法(ヘッダ)
つまり、波形さえ作れれば、どんな音でも自作できます
ゲーム音、効果音、楽器音、シンセ音などはすべて「波形の組み合わせ」で作れます。
まとめ
- WAV は 波形(振幅の数値列)を保存したシンプルなフォーマット
- ヘッダに「どう再生すべきか」を書いているだけ
- 波形を整数に変換すれば WAV が作れる
- Python で簡単に波形 → WAV → 再生が可能
波形を理解すると「音を作る」自由度が上がります。
ぜひいろいろな音を自作してみてください!

