2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WAV の仕組みを理解:波形から音を作る

2
Posted at

この記事について

音声ファイルの中でも最もシンプルで構造が分かりやすいフォーマットが WAV(Waveform Audio File Format) です。

WAV はその名のとおり 「波形(waveform)」をそのまま保存したファイルであり、複雑な圧縮もありません。

この記事では以下について解説します

  • WAV はどのように波形を保存しているのか
  • 波形とはそもそも何か
  • Python を使って波形を描く
  • 波形から WAV を生成して音を鳴らす

1. そもそも音とは?

音とは「空気の振動」です。
スピーカーは膜を前後に震わせ、この震えが空気を押したり引いたりします。

これを時間軸に沿って数値化したものが 波形データ(waveform)です。

2. 波形(waveform)とは?

波形とは「時刻 t における空気の振幅を数値で並べたもの」です。

例えば、440Hz(A/ラの音)は次の正弦波になります。

y(t)=sin(2π⋅440⋅t)

image.png
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()

実行結果

スクリーンショット 2025-12-14 17.23.17.png

この波形を拡大すると「スピーカーが前後に振れる量」が見えるわけです。

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()

実行結果
スクリーンショット 2025-12-14 17.26.31.png

上記波形のscale.wavファイルも生成されます

6. WAV の本質:波形をそのまま保存したファイル

WAVはシンプルで、この2つだけで構成されます。

  • 波形(振幅の数値列)
  • そのデータの解釈方法(ヘッダ)

つまり、波形さえ作れれば、どんな音でも自作できます

ゲーム音、効果音、楽器音、シンセ音などはすべて「波形の組み合わせ」で作れます。

まとめ

  • WAV は 波形(振幅の数値列)を保存したシンプルなフォーマット
  • ヘッダに「どう再生すべきか」を書いているだけ
  • 波形を整数に変換すれば WAV が作れる
  • Python で簡単に波形 → WAV → 再生が可能

波形を理解すると「音を作る」自由度が上がります。
ぜひいろいろな音を自作してみてください!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?