0) 前提(量子化ノイズのモデル)
-
量子化間隔:$\Delta$(LSB)
-
量子化誤差 $e[n]$ は一様 $\mathcal U(-\Delta/2,\Delta/2)$ と仮定(入力と無相関・微小信号・適切なディザ)
-
分散:$\sigma_q^2=\Delta^2/12$
-
サンプリング周波数 $f_s$。離散時間PSDは白色で一定:
$$
S_q(f)=\frac{\Delta^2}{12,f_s}\quad(0\le f\le f_s/2)
$$ -
信号帯域幅:$B$(低域ベースバンド)。オーバーサンプリング比:
$$
\mathrm{OSR}=\frac{f_s}{2B}
$$
1) 通常のサンプリング(Nyquist, OSR=1)
-
横軸:周波数 $0\to f_s$(実用上は $0\to f_s/2$)
-
縦軸:ノイズ密度(PSD)
-
形:高さ一定の赤い長方形(白色)
-
信号帯域内ノイズ電力(面積):
$$
P_{\text{in}}=\int_{0}^{B}S_q(f),df
=\frac{\Delta^2}{12,f_s},B
\quad(\text{片側表示なら }B=f_s/2)
$$
2) オーバーサンプリング(図2-1 上段→下段)
-
$f_s\to M f_s$(図では横軸が $M f_s$ まで伸びる)
-
総ノイズ電力は一定($\sigma_q^2$)だが,分布帯域が広がるため密度(高さ)は同じでもベースバンドに「入ってくる面積」が減る
-
計算:
$$
P_{\text{in}}=\int_{0}^{B}\frac{\Delta^2}{12,M f_s},df
=\frac{1}{M}\cdot\frac{\Delta^2}{12}\cdot\frac{B}{f_s}
\propto\frac{1}{\mathrm{OSR}}
$$ -
結論:OSRを $2$ 倍にすると3 dB(=約0.5 bit)SNR改善
$$
\Delta \mathrm{SNR}\approx 10\log_{10}(\mathrm{OSR}),[\mathrm{dB}]
$$
作図ポイント
- 通常サンプリング:赤の長方形(0~$f_s/2$)
- オーバーサンプリング:同じ高さの赤長方形を0~$M f_s/2$まで横に伸ばす。ベースバンド(0~$f_s/2$)の塗りつぶし面積が相対的に小さくなるよう薄く示す。
3) 「一般的な量子化器」の図(図2-2 上段)
- フィードバック無し=ノイズ整形なし。PSDはフラット。
- したがって、上のオーバーサンプリングと同じ理屈で低域ノイズは $1/\mathrm{OSR}$でしか減らない。図ではほぼ水平な赤帯。
4) ΔΣ変調(ノイズシェーピング:図2-2 下段)
4.1 ノイズ伝達関数
-
$L$ 次ΔΣ(ループ内に $L$ 個の理想積分器)では
$$
\mathrm{NTF}(z)=(1-z^{-1})^{L}
$$周波数特性:
$$
\bigl|\mathrm{NTF}(e^{j\omega})\bigr|^{2}
=\bigl(2\sin(\tfrac{\omega}{2})\bigr)^{2L}
\approx(\omega)^{2L}\quad(\omega\ll 1)
$$ -
出力ノイズPSD:
$$
S_{y}(f)=S_q(f)\cdot\bigl|\mathrm{NTF}(e^{j2\pi f/f_s})\bigr|^{2}
$$→ 低周波で強く抑圧され,高域へ「押し出される」。
4.2 ベースバンドノイズの積分
-
近似的に(低域 $\sin x\approx x$):
$$
P_{\text{in}};\approx;\frac{\Delta^2}{12}\cdot
\frac{\pi^{2L}}{(2L+1)}\cdot\frac{1}{\mathrm{OSR}^{,2L+1}}
\quad(\text{比例定数は教科書により表記差あり})
$$ -
スケーリングが本質:
$$
P_{\text{in}}\propto \mathrm{OSR}^{-(2L+1)}
$$→ OSRを2倍にするたびに**$(2L+1)\times 3$ dB** 改善
- $L=0$(整形なし): 3 dB/倍
- $L=1$(一次ΔΣ): 9 dB/倍 ≈ 1.5 bit/倍
- $L=2$(二次): 15 dB/倍 ≈ 2.5 bit/倍
4.3 形状の描き分け
- 一次ΔΣ:$|\mathrm{NTF}|^2\propto f^{2}$ ⇒ 左が低く右が高い“直線的に増える三角形”
- 二次ΔΣ:$\propto f^{4}$ ⇒ 低域がさらに深く抑圧され、右端で急峻に立ち上がるカーブ
- 図2-2下段は一次の典型(赤の右上がりの斜面)。
作図ポイント
- 横軸:0~$M f_s$(または規格化 0~$\pi$)
- 縦軸:ノイズ密度。ベースバンド0~$f_s/2$を薄い縦帯で示す
- 一般量子化器:赤は水平
- ΔΣ:赤は原点から右上がり(一次)/S字急増(二次)
- 左端の「灰色の信号帯域」(図中の高い棒)は通過信号のイメージ。最終的にデジタルLPF+デシメーションで高域ノイズを除去してから低サンプルレートへ落とす。
5) SNR/ENOBのよく使う近似式
-
フルスケール正弦入力のSNR(dB)おおよそ:
$$
\mathrm{SNR}\approx 6.02N+1.76
+10(2L+1)\log_{10}(\mathrm{OSR})
-10\log_{10}!\Bigl(C_L\Bigr)
$$($N$:量子化器ビット数,$C_L$ は $\pi^{2L}/(2L+1)$ 由来の定数)
-
ENOB:$\mathrm{ENOB}\approx(\mathrm{SNR}-1.76)/6.02$
6) 図を描く“手順メモ”(手で描く/コードで描く共通)
-
軸を用意:横=周波数,縦=ノイズ密度。
-
通常:赤の水平帯(0~$f_s/2$)。
-
OSR $M$:横軸を0~$M f_s/2$に拡大し,赤水平帯を横に延ばす。ベースバンド内の赤面積を薄く。
-
一般量子化器:赤=水平。
-
ΔΣ(一次):0から右上がりの直線(三角)を赤で塗る。中央$(M f_s)/2$ 位置などに目盛り。
-
凡例やラベルは
- 横軸:Frequency
- 縦軸:Noise Power Spectral Density
- ラベル:Normal sampling / Oversampling / Generic quantizer / ΔΣ modulator / Quantization noise / $M f_s$, $(M f_s)/2$
7) 注意点
- ノイズ白色化はディザや「入力とノイズが無相関」という仮定が要る。入力依存のスペクトルラインやリミットサイクルが出る場合は別途対策。
- 実機ではループ安定性(二次以上,マルチビットDACの線形性,オペアンプ帯域など)で理想形から崩れる。
- 図の赤の“面積”が帯域内ノイズ電力に対応し,LPF+デシメーション後のSNRと直結。
# Program Name: noise_shaping_demo.py
# Creation Date: 20250920
# Overview: Illustrate quantization noise distribution
# (normal sampling, oversampling, generic quantizer, ΔΣ modulator)
import numpy as np
import matplotlib.pyplot as plt
# ========================
# Parameters / パラメータ
# ========================
fs = 1.0 # 基準サンプリング周波数 [normalized]
M = 4 # Oversampling factor
N_points = 1000 # Plot resolution
f = np.linspace(0, M*fs, N_points)
# ========================
# Noise PSD models / ノイズPSDモデル
# ========================
# 1. Normal sampling (flat up to fs/2)
psd_normal = np.where(f <= fs/2, 1.0, 0.0)
# 2. Oversampling (flat up to M*fs/2, same height)
psd_oversample = np.where(f <= M*fs/2, 1.0, 0.0)
# 3. Generic quantizer (flat, no shaping)
psd_generic = np.where(f <= M*fs/2, 1.0, 0.0)
# 4. ΔΣ modulator (1st-order shaping: ~ f^2)
psd_dsm = np.where(f <= M*fs/2, (f/(M*fs/2))**2, 0.0)
# ========================
# Plot / プロット
# ========================
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle("Quantization Noise Distributions")
# --- 1. Normal sampling
axs[0,0].plot(f, psd_normal, color="red")
axs[0,0].fill_between(f, 0, psd_normal, color="red", alpha=0.6)
axs[0,0].set_title("Normal Sampling")
axs[0,0].set_xlabel("Frequency [normalized]")
axs[0,0].set_ylabel("Noise PSD")
axs[0,0].set_xlim(0, fs)
axs[0,0].set_ylim(0, 1.2)
# --- 2. Oversampling
axs[0,1].plot(f, psd_oversample, color="red")
axs[0,1].fill_between(f, 0, psd_oversample, color="red", alpha=0.6)
axs[0,1].set_title(f"Oversampling (M={M})")
axs[0,1].set_xlabel("Frequency [normalized]")
axs[0,1].set_ylabel("Noise PSD")
axs[0,1].set_xlim(0, M*fs)
axs[0,1].set_ylim(0, 1.2)
# --- 3. Generic quantizer
axs[1,0].plot(f, psd_generic, color="red")
axs[1,0].fill_between(f, 0, psd_generic, color="red", alpha=0.6)
axs[1,0].set_title("Generic Quantizer (flat PSD)")
axs[1,0].set_xlabel("Frequency [normalized]")
axs[1,0].set_ylabel("Noise PSD")
axs[1,0].set_xlim(0, M*fs)
axs[1,0].set_ylim(0, 1.2)
# --- 4. ΔΣ modulator (1st-order)
axs[1,1].plot(f, psd_dsm, color="red")
axs[1,1].fill_between(f, 0, psd_dsm, color="red", alpha=0.6)
axs[1,1].set_title("ΔΣ Modulator (1st-order shaping)")
axs[1,1].set_xlabel("Frequency [normalized]")
axs[1,1].set_ylabel("Noise PSD")
axs[1,1].set_xlim(0, M*fs)
axs[1,1].set_ylim(0, 1.2)
plt.tight_layout()
plt.show()