はじめに
マイクで録音された音声、心電図センサーが計測した生体信号、レーダーが受信したRF波――これらはすべてアナログ信号です。現代のデジタル信号処理システムはこれらを扱うために、まずアナログ信号を離散的な数値列に変換する必要があります。この変換プロセスが標本化(サンプリング)であり、その根幹をなす理論がナイキスト-シャノンのサンプリング定理です。
サンプリング定理は「どれだけの速さでサンプルを取得すれば、元のアナログ信号を完全に復元できるか」という問いに対する厳密な答えを与えます。この定理を正しく理解しないと、エイリアシングと呼ばれる深刻な信号歪みが生じ、50Hzの電源ノイズが10Hzに見えたり、高速回転するプロペラがゆっくり逆回転しているように見えたりする現象が起こります。
本記事では、サンプリングの数学的モデルからナイキスト-シャノン定理の証明、エイリアシングの仕組み、アンチエイリアシングフィルタの設計、そしてPythonによる完全な実装まで体系的に解説します。関連する周波数解析の基礎については FFTの仕組みとPython実装 も合わせてご参照ください。
アナログ信号のデジタル化(A/D変換)
サンプリングの必要性
アナログ-デジタル変換器(ADC)は、連続時間信号 \(x(t)\) を等間隔の時刻 \(t = nT_s\) (\(n \in \mathbb{Z}\) )でサンプリングし、離散値列 \(x[n] = x(nT_s)\) を生成します。ここで \(T_s\) はサンプリング周期、その逆数 \(f_s = 1/T_s\) がサンプリング周波数(単位: Hz)です。
実際のADCは量子化も行いますが、本記事では理想的なサンプリング(量子化誤差なし)を仮定し、純粋にサンプリング周波数の選択が信号品質に与える影響に焦点を当てます。
インパルス列による数学的モデル
理想サンプリングは、アナログ信号 \(x(t)\) にディラックのインパルス列(シャー関数)\(s(t)\) を乗算する操作として数学的にモデル化されます。
\[s(t) = \sum_{n=-\infty}^{\infty} \delta(t - nT_s) \tag{1}\]サンプリングされた信号 \(x_s(t)\) は次のようになります。
\[x_s(t) = x(t) \cdot s(t) = \sum_{n=-\infty}^{\infty} x(nT_s)\, \delta(t - nT_s) \tag{2}\]この表現の重要な点は、\(x_s(t)\) が実数値列 \(x[n] = x(nT_s)\) を完全に保持していることです。連続時間信号から離散時間信号への情報の「圧縮」です。
サンプリングのスペクトルへの影響
式 \((2)\) をフーリエ変換すると、乗算は畳み込みになります。時間領域での積はスペクトル領域での畳み込みに対応するため:
\[X_s(f) = X(f) * S(f) \tag{3}\]インパルス列のフーリエ変換は再びインパルス列です。
\[S(f) = f_s \sum_{k=-\infty}^{\infty} \delta(f - kf_s) \tag{4}\]これを式 \((3)\) に代入すると:
\[X_s(f) = f_s \sum_{k=-\infty}^{\infty} X(f - kf_s) \tag{5}\]式 \((5)\) が示す本質:サンプリング後のスペクトルは、元のスペクトル \(X(f)\) をサンプリング周波数 \(f_s\) の整数倍だけシフトしたものをすべて重ね合わせた(スペクトルの複製)ものです。
ナイキスト-シャノンのサンプリング定理
定理の陳述
定理(Nyquist-Shannon):帯域制限信号 \(x(t)\) (\(|f| > f_{\max}\) で \(X(f) = 0\) )は、サンプリング周波数が次の条件を満たす場合に、サンプル列 \(\{x[n]\}\) から完全に復元できる。
\[f_s > 2 f_{\max} \tag{6}\]この条件を満たす最小サンプリング周波数 \(2f_{\max}\) をナイキストレートと呼びます。
証明のスケッチ
式 \((5)\) から、スペクトル複製が互いに重ならない条件を考えます。\(k=0\) の複製(元のスペクトル)の帯域幅は \([-f_{\max}, f_{\max}]\) です。隣の複製(\(k=\pm 1\) )は \([f_s - f_{\max}, f_s + f_{\max}]\) に位置します。
これらが重なり合わないための条件は:
\[f_{\max} < f_s - f_{\max}\] \[\Rightarrow f_s > 2f_{\max} \tag{7}\]この条件が満たされれば、\(X_s(f)\) から理想ローパスフィルタ(カットオフ周波数 \(f_s/2\) 、ゲイン \(1/f_s\) )を適用することで \(X(f)\) を完全に取り出せます。
sinc補間による完全復元
時間領域での完全復元はsinc補間で表されます。
\[x(t) = \sum_{n=-\infty}^{\infty} x[n] \cdot \text{sinc}(f_s t - n) \tag{8}\]ここで \(\text{sinc}(u) = \sin(\pi u) / (\pi u)\) はsinc関数です。各サンプル \(x[n]\) は、時刻 \(n/f_s\) を中心とするsinc関数で重み付けされ、これらの無限和が元の連続信号を再構成します。
式 \((8)\) の意味:デジタル信号からアナログ信号を復元する理想D/A変換は、sinc関数を基底とする補間です。これが周波数領域での理想LPFと等価であることはフーリエ変換から明らかです。
エイリアシング
エイリアシングの発生メカニズム
\(f_s < 2f_{\max}\) の場合、スペクトルの複製が重なり合います(エイリアシング)。式 \((5)\) で \(k=0\) と \(k=-1\) の複製を考えると:
\[X_{\text{alias}}(f) \ni X(f) + X(f + f_s) \tag{9}\]この重なりは情報の不可逆な混合であり、もはや元の信号を分離して復元することはできません。
エイリアス周波数の計算
周波数 \(f\) の成分がサンプリング周波数 \(f_s\) でサンプリングされた場合、観測されるエイリアス周波数は次の式で計算されます。
\[f_\text{alias} = \left| f - \text{round}\left(\frac{f}{f_s}\right) \cdot f_s \right| \tag{10}\]例として、\(f_s = 1000\) Hz で \(f = 1300\) Hz の信号をサンプリングすると:
\[f_\text{alias} = |1300 - \text{round}(1300/1000) \times 1000| = |1300 - 1000| = 300 \text{ Hz}\]1300Hzの信号が300Hzとして観測されます。
ウェゴンホイール効果
映画やビデオで高速回転する車輪が逆回転しているように見える「ウェゴンホイール効果(Wagon Wheel Effect)」は、エイリアシングの直感的な例です。カメラのフレームレート(サンプリング周波数)より速く回転すると、ナイキスト条件が破られ、折り返しが起きて逆方向に見えます。
具体的に、フレームレート \(f_s = 24\) fps のカメラで 1 回転/フレーム より速い 1.1 回転/フレーム(\(f = 26.4\) Hz)の車輪を撮影した場合:
\[f_\text{alias} = |26.4 - \text{round}(26.4/24) \times 24| = |26.4 - 24| = 2.4 \text{ Hz}\]車輪は実際より100倍遅い 2.4 Hz(1/2.4秒で1回転)でゆっくり回転しているように見えます。
ナイキスト周波数とナイキストレートの違い
この2つの用語は混同されやすいため、明確に区別します。
| 用語 | 定義 | 意味 |
|---|---|---|
| ナイキスト周波数 \(f_N\) | \(f_N = f_s / 2\) | 与えられたサンプリング周波数で表現できる最大周波数 |
| ナイキストレート \(f_{NR}\) | \(f_{NR} = 2 f_{\max}\) | 信号を完全に復元するために必要な最小サンプリング周波数 |
ナイキスト周波数はシステムの「能力」を表します。サンプリング周波数44.1 kHz(CDの規格)のシステムは最大22.05 kHzまでの信号を表現できます。人間の可聴域(約20 kHz)をカバーするために選ばれた値です。
ナイキストレートは信号の「要求」を表します。最高周波数20 kHzの音声信号を完全に復元したければ、少なくとも40 kHz以上でサンプリングする必要があります。
エイリアシングを防ぐ条件は「ナイキスト周波数 ≥ 信号の最高周波数」、すなわち「サンプリング周波数 ≥ ナイキストレート」と等価です。
アンチエイリアシングフィルタの設計
なぜADC前にLPFが必要か
実際のアナログ信号は有限帯域ではありません。センサーノイズ、EMI、電源ハムなど、意図しない高周波成分が常に存在します。これらをサンプリング前に除去しないと、ナイキスト周波数以上の全成分がエイリアシングを引き起こします。
**アンチエイリアシングフィルタ(AAF)**は、ADCの直前に配置するアナログローパスフィルタです。カットオフ周波数 \(f_c\) を \(f_s/2\) 以下に設定し、エイリアシングの原因となる高周波成分を事前に除去します。
カットオフ周波数の選択
理想的なAAFは遷移帯域が無限に急峻なブリック・ウォールフィルタですが、現実には実現不可能です。実用的な設計では次の考慮が必要です。
- 通過域上限 \(f_p\) :保持したい信号の最高周波数(例: 音声なら20 kHz)
- 阻止域下限 \(f_{stop}\) :エイリアシングを確実に防ぐ周波数(\(= f_s - f_p\) )
- 遷移帯域 \([f_p, f_{stop}]\) :この帯域でどれだけ急峻に減衰できるかがフィルタの次数を決定する
オーバーサンプリングによって \(f_s/2\) と \(f_{\max}\) の間のマージンを大きくすれば、より緩やかな(低次数の)アナログフィルタで十分になります。これはCDオーディオで \(f_{\max} = 20\) kHz に対して \(f_s = 44.1\) kHz(マージン: 4.1 kHz)が選ばれた設計理由の一つです。
バターワースフィルタやチェビシェフフィルタの詳細な設計については バターワースフィルタの設計 をご参照ください。
Pythonによる実装
実装1:エイリアシングの可視化
まず、エイリアシングが発生する状況を時間領域と周波数領域の両方で可視化します。
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, sosfilt, resample, freqz
# --- パラメータ設定 ---
f_signal = 130 # 信号周波数 [Hz]
fs_high = 1000 # 十分高いサンプリング周波数(エイリアシングなし)
fs_low = 200 # 不十分なサンプリング周波数(エイリアシング発生)
duration = 0.1 # 表示時間 [s]
# --- 元の信号(高サンプリングレートで生成)---
t_high = np.arange(0, duration, 1 / fs_high)
x_orig = np.sin(2 * np.pi * f_signal * t_high)
# --- 低サンプリングレートでサンプリング ---
t_low = np.arange(0, duration, 1 / fs_low)
x_alias = np.sin(2 * np.pi * f_signal * t_low)
# エイリアス周波数を計算式で確認
f_alias = abs(f_signal - round(f_signal / fs_low) * fs_low)
print(f"信号周波数: {f_signal} Hz")
print(f"サンプリング周波数: {fs_low} Hz (ナイキスト: {fs_low//2} Hz)")
print(f"エイリアス周波数: {f_alias} Hz")
# => エイリアス周波数: 70 Hz
# --- プロット(時間領域) ---
fig, axes = plt.subplots(2, 1, figsize=(10, 6))
axes[0].plot(t_high * 1000, x_orig, 'b-', label=f'元信号 ({f_signal} Hz)', lw=1.5)
axes[0].plot(t_low * 1000, x_alias, 'ro', ms=8, label=f'低fs={fs_low}Hzでのサンプル')
# エイリアス波形を重ねて表示
t_fine = np.linspace(0, duration, 2000)
axes[0].plot(t_fine * 1000,
np.sin(2 * np.pi * f_alias * t_fine),
'r--', lw=1.5, label=f'エイリアス波形 ({f_alias} Hz)')
axes[0].set_xlabel('Time [ms]')
axes[0].set_ylabel('Amplitude')
axes[0].set_title('エイリアシング:時間領域')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# --- FFTによる周波数領域の比較 ---
N_high = len(x_orig)
N_low = len(x_alias)
X_high = np.fft.rfft(x_orig)
X_low = np.fft.rfft(x_alias)
freqs_high = np.fft.rfftfreq(N_high, 1 / fs_high)
freqs_low = np.fft.rfftfreq(N_low, 1 / fs_low)
axes[1].plot(freqs_high, 2 / N_high * np.abs(X_high),
'b-', label=f'fs={fs_high} Hz(エイリアシングなし)')
axes[1].plot(freqs_low, 2 / N_low * np.abs(X_low),
'r-', label=f'fs={fs_low} Hz(エイリアシングあり)')
axes[1].axvline(fs_low / 2, color='k', ls='--', label=f'ナイキスト周波数 ({fs_low//2} Hz)')
axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Amplitude')
axes[1].set_title('エイリアシング:周波数領域')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このコードを実行すると、130Hzの信号が200Hzでサンプリングされることで70Hzとして現れることが時間領域・周波数領域の両方で確認できます。
実装2:スペクトル折り返しの全貌
サンプリング周波数に対して様々な周波数の信号がどの周波数に折り返されるかを系統的に示します。
import numpy as np
import matplotlib.pyplot as plt
fs = 1000 # サンプリング周波数 [Hz]
fn = fs / 2 # ナイキスト周波数
# 様々な入力周波数に対するエイリアス周波数を計算
f_input = np.linspace(0, 3 * fs, 3000)
f_alias = np.abs(f_input - np.round(f_input / fs) * fs)
plt.figure(figsize=(10, 5))
plt.plot(f_input, f_alias, 'b-', lw=2)
plt.axhline(fn, color='r', ls='--', label=f'ナイキスト周波数 = {fn:.0f} Hz')
plt.fill_between([0, fn], [0, 0], [fn, fn],
alpha=0.1, color='green', label='エイリアスなし領域')
plt.xlabel('入力周波数 [Hz]')
plt.ylabel('観測周波数(エイリアス周波数)[Hz]')
plt.title(f'周波数折り返し特性 (fs = {fs} Hz)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.ylim(0, fn * 1.1)
plt.tight_layout()
plt.show()
このグラフの鋸歯状パターンがナイキスト周波数での「折り返し」を視覚的に示します。\(0\) から \(f_s/2\) の間の信号はそのまま観測されますが、\(f_s/2\) を超えると折り返しが始まり、\(3f_s/2\) で再び \(f_s/2\) から折り返すという周期的なパターンが繰り返されます。
実装3:アンチエイリアシングフィルタの効果
ADC前にアンチエイリアシングフィルタを適用した場合と適用しない場合を比較します。
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, sosfilt, freqz
np.random.seed(42)
# --- 帯域外成分を含む信号の生成 ---
fs_orig = 10000 # 元の高サンプリングレート [Hz]
fs_target = 1000 # ダウンサンプリング後のレート [Hz]
M = fs_orig // fs_target # ダウンサンプリング比
duration = 0.5
t = np.arange(0, duration, 1 / fs_orig)
# 帯域内信号(100Hz)+ 帯域外信号(600Hz: ダウン後にエイリアシング)
x = np.sin(2 * np.pi * 100 * t) + 0.5 * np.sin(2 * np.pi * 600 * t)
# --- アンチエイリアシングフィルタの設計(バターワース LPF)---
# カットオフ: ナイキスト周波数の0.9倍
fc = (fs_target / 2) * 0.9 # = 450 Hz
sos = butter(8, fc, btype='low', fs=fs_orig, output='sos')
x_filtered = sosfilt(sos, x)
# --- ダウンサンプリング(AAFなし vs あり)---
x_down_noaaf = x[::M] # AAFなし
x_down_aaf = x_filtered[::M] # AAFあり
# --- 周波数応答の比較 ---
N_down = len(x_down_noaaf)
freqs_down = np.fft.rfftfreq(N_down, 1 / fs_target)
X_noaaf = np.fft.rfft(x_down_noaaf)
X_aaf = np.fft.rfft(x_down_aaf)
fig, axes = plt.subplots(3, 1, figsize=(10, 10))
# フィルタの周波数応答
w, h = freqz(sos, worN=2048, fs=fs_orig, whole=False)
axes[0].plot(w, 20 * np.log10(np.abs(h) + 1e-12), 'b-', lw=2)
axes[0].axvline(fc, color='r', ls='--', label=f'カットオフ fc = {fc:.0f} Hz')
axes[0].axvline(fs_target / 2, color='g', ls='--',
label=f'ナイキスト周波数 = {fs_target//2} Hz')
axes[0].set_xlabel('Frequency [Hz]')
axes[0].set_ylabel('Magnitude [dB]')
axes[0].set_title('アンチエイリアシングフィルタの周波数応答(8次バターワース)')
axes[0].set_xlim(0, 2000)
axes[0].set_ylim(-80, 5)
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# AAFなしのスペクトル
axes[1].plot(freqs_down, 20 * np.log10(2 / N_down * np.abs(X_noaaf) + 1e-12),
'r-', lw=1.5)
axes[1].axvline(fs_target / 2, color='k', ls='--', alpha=0.5)
axes[1].set_title('ダウンサンプリング後のスペクトル(AAFなし)— 600Hzが400Hzにエイリアス')
axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Magnitude [dB]')
axes[1].set_xlim(0, fs_target / 2)
axes[1].grid(True, alpha=0.3)
# AAFありのスペクトル
axes[2].plot(freqs_down, 20 * np.log10(2 / N_down * np.abs(X_aaf) + 1e-12),
'b-', lw=1.5)
axes[2].axvline(fs_target / 2, color='k', ls='--', alpha=0.5)
axes[2].set_title('ダウンサンプリング後のスペクトル(AAFあり)— エイリアスが除去')
axes[2].set_xlabel('Frequency [Hz]')
axes[2].set_ylabel('Magnitude [dB]')
axes[2].set_xlim(0, fs_target / 2)
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
600Hzの成分は1000HzのナイキストFs/2=500Hzを超えているため、AAFなしでは \(|600 - 1000| = 400\) Hzにエイリアシングします。8次バターワースフィルタを適用することでこの成分を除去し、クリーンなスペクトルが得られます。
実装4:scipy.signal.resampleによるリサンプリング
scipy.signal.resample はFFTベースのリサンプリングを実装しており、アップサンプリングとダウンサンプリングの両方に利用できます。
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import resample, butter, sosfilt
# --- 元信号の生成 ---
fs_orig = 1000 # 元のサンプリングレート
duration = 1.0
t_orig = np.arange(0, duration, 1 / fs_orig)
x_orig = (np.sin(2 * np.pi * 50 * t_orig)
+ 0.3 * np.sin(2 * np.pi * 120 * t_orig))
# --- ダウンサンプリング(1000 Hz → 400 Hz、デシメーション比 M=2.5)---
fs_down = 400
n_down = int(len(x_orig) * fs_down / fs_orig)
x_down = resample(x_orig, n_down) # FFTベース:内部でAAFを適用
t_down = np.linspace(0, duration, n_down)
# --- アップサンプリング(元の1000 Hz → 4000 Hz)---
fs_up = 4000
n_up = int(len(x_orig) * fs_up / fs_orig)
x_up = resample(x_orig, n_up) # 補間によるアップサンプリング
t_up = np.linspace(0, duration, n_up)
# --- スペクトル比較 ---
def spectrum(x, fs):
N = len(x)
X = np.fft.rfft(x)
f = np.fft.rfftfreq(N, 1 / fs)
return f, 2 / N * np.abs(X)
fig, axes = plt.subplots(3, 1, figsize=(10, 9))
f_orig, A_orig = spectrum(x_orig, fs_orig)
f_down, A_down = spectrum(x_down, fs_down)
f_up, A_up = spectrum(x_up, fs_up)
axes[0].plot(f_orig, A_orig, 'b-')
axes[0].set_title(f'元信号のスペクトル (fs = {fs_orig} Hz)')
axes[0].set_ylabel('Amplitude')
axes[0].set_xlim(0, fs_orig / 2)
axes[0].grid(True, alpha=0.3)
axes[1].plot(f_down, A_down, 'r-')
axes[1].set_title(f'ダウンサンプリング後 (fs = {fs_down} Hz)')
axes[1].set_ylabel('Amplitude')
axes[1].set_xlim(0, fs_down / 2)
axes[1].grid(True, alpha=0.3)
axes[2].plot(f_up, A_up, 'g-')
axes[2].set_title(f'アップサンプリング後 (fs = {fs_up} Hz)')
axes[2].set_ylabel('Amplitude')
axes[2].set_xlabel('Frequency [Hz]')
axes[2].set_xlim(0, fs_up / 2)
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"元信号: {len(x_orig)} サンプル ({fs_orig} Hz)")
print(f"ダウンサンプリング: {len(x_down)} サンプル ({fs_down} Hz)")
print(f"アップサンプリング: {len(x_up)} サンプル ({fs_up} Hz)")
scipy.signal.resample はFFTによってスペクトルを計算し、必要なサンプル数にトリミング(ダウンサンプリング)またはゼロ埋め(アップサンプリング)してIDFFTを適用します。この手法は内部的にアンチエイリアシングを処理しますが、任意比のリサンプリングが可能という利点があります。
アップサンプリングとダウンサンプリング
デシメーション(ダウンサンプリング)
整数比 \(M\) のダウンサンプリング(デシメーション)は次の手順で行います。
- アンチエイリアシングLPF:カットオフ \(f_s/(2M)\) でフィルタリング
- \(M\) サンプルに1つを保持:\(y[n] = x[Mn]\)
手順1を省略すると、新しいナイキスト周波数 \(f_s/(2M)\)
を超える成分がエイリアシングを起こします。scipy.signal.decimate はこの2段階を自動処理します。
補間(アップサンプリング)
整数比 \(L\) のアップサンプリング(補間)は次の手順で行います。
- ゼロ挿入:\(L-1\) 個のゼロを各サンプル間に挿入
- イメージ除去LPF:カットオフ \(f_s/(2L)\) (ゲイン \(L\) )でフィルタリング
ゼロ挿入だけではスペクトルに「イメージ」(スペクトルの複製)が残るため、LPFで除去します。
\[x_L[n] = \begin{cases} x[n/L] & n \text{ が } L \text{ の倍数} \\ 0 & \text{その他} \end{cases} \tag{13}\]ポリフェーズフィルタリング
実用的なリサンプリング実装では、ポリフェーズフィルタが用いられます。ポリフェーズ分解により、フィルタを \(L\) 個のサブフィルタに分解し、ゼロ乗算を避けることで計算効率を大幅に改善します。計算量は素朴な実装の \(1/L\) になります。
scipy.signal.resample_poly はポリフェーズフィルタリングを実装した高効率なリサンプリング関数です。任意の有理数比 \(L/M\)
のリサンプリングが可能です。
from scipy.signal import resample_poly
# 1000 Hz → 441 Hz(L=441, M=1000 のポリフェーズ)
x_poly = resample_poly(x_orig, 441, 1000)
print(f"ポリフェーズリサンプリング: {len(x_orig)} → {len(x_poly)} サンプル")
まとめ
本記事で解説した内容を次の表にまとめます。
| 概念 | 定義 | ポイント |
|---|---|---|
| サンプリング定理 | \(f_s > 2f_{\max}\) | この条件が完全復元の必要十分条件 |
| ナイキスト周波数 | \(f_N = f_s / 2\) | システムが表現できる最大周波数 |
| ナイキストレート | \(f_{NR} = 2f_{\max}\) | 信号に要求される最小サンプリング周波数 |
| エイリアス周波数 | \(f_\text{alias} = \|f - \text{round}(f/f_s)\cdot f_s\|\) | 折り返し後の観測周波数 |
| アンチエイリアシングフィルタ | ADC前のアナログLPF | カットオフ \(\leq f_s/2\) 、ダウンサンプリング前に必須 |
| デシメーション | AAF → \(M\) サンプルに1つ保持 | scipy.signal.decimate |
| 補間 | ゼロ挿入 → イメージ除去LPF | scipy.signal.resample_poly |
サンプリング理論の理解は、DSPシステム設計の出発点です。窓関数とPSDの理論、ローパスフィルタの設計と比較 などと合わせて、信号処理パイプライン全体を俯瞰することを推奨します。
関連記事
- 高速フーリエ変換(FFT)の仕組みとPython実装 - サンプリングされた離散信号の周波数解析の基礎。FFTはサンプリング定理と密接に関連しています。
- 窓関数とパワースペクトル密度(PSD)の理論とPython実装 - サンプリング後のスペクトル解析における窓関数の役割とPSD推定を解説しています。
- ローパスフィルタの設計と比較 - アンチエイリアシングフィルタの設計に直結するLPFの種類と比較です。
- バターワースフィルタの設計とPython実装 - アンチエイリアシングフィルタとして最もよく使われるバターワースフィルタの詳細設計です。
参考文献
- Shannon, C. E. (1949). “Communication in the Presence of Noise”. Proceedings of the IRE, 37(1), 10-21.
- Nyquist, H. (1928). “Certain Topics in Telegraph Transmission Theory”. Transactions of the AIEE, 47(2), 617-644.
- Oppenheim, A. V., & Schafer, R. W. (2009). Discrete-Time Signal Processing (3rd ed.). Prentice Hall.
- Proakis, J. G., & Manolakis, D. G. (2006). Digital Signal Processing (4th ed.). Prentice Hall.
- SciPy Signal Processing documentation