首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >噪音需要达到什么程度才“足以有效打散量化伪像”

噪音需要达到什么程度才“足以有效打散量化伪像”

作者头像
云深无际
发布于 2025-05-23 05:10:07
发布于 2025-05-23 05:10:07
20400
代码可运行
举报
文章被收录于专栏:云深之无迹云深之无迹
运行总次数:0
代码可运行

通俗的解读一下:当给 ADC 输入一个干净的正弦波,而且这个频率刚好是采样频率的整数倍时,会出现奇怪的频谱伪像——明明没有失真、没有噪声,却在 FFT 里看到很多“鬼影”(假的频率成分)。为了打破这个“相关性陷阱”,我们尝试往输入信号里加入一点点扰动(也叫“加抖”、“抖码”、“打散”),让每次采样点不会总是重复。这也是今天文章要解决的问题。

这个问题
这个问题

这个问题

其实这个问题问的不准,不如这样说:为了打破输入频率与采样频率相关性而引入的噪声(或扰动),其大小需要达到什么程度才“足以有效打散量化伪像”。

MT-001
MT-001

MT-001

在这里,初看不知他在叽里咕噜什么,但是仔细分析感觉是一个非常有趣的话题,我觉得可以计算一下。

说啥呢?

为什么要加噪声?我们不是最怕噪音了吗?

当 ADC 输入是一个频率与采样率成整数比的纯正弦波,如:

在这种情况下:

采样点总是落在信号的固定相位点,导致输出“周期性重复码字”,FFT 显示“完美的谐波结构”而非真实量化噪声(我们的FFT会看到很多的尖刺,其实就是谐波),这不是 ADC 真正的 SNR,而是被误导的高伪像分布


文档中解决方法:加扰动噪声(Dithering)

目标是:

“打破 ADC 采样点与输入波形的固定相位关系”,从而使量化误差“变得随机”

要加多大的扰动才能有效?

MT-001 的经验公式如下:

扰动噪声的峰值幅度至少要达到 ±0.5 LSB,理想值为 ±1 LSB

也可以直观的看:

量化误差
量化误差

量化误差

1 LSB 的最小码间隔定义了量化台阶,若扰动小于 0.5 LSB,则采样值仍会集中在固定码;达到 ±1 LSB,才能有效“跨越码间界限”,使量化行为去相关。

但是这样说就太没有说服力了!接下来就使用数学的方法来研究一下。问题涉及量化误差的统计扰动模型,可以从量化误差的均值、方差、相关性分析出发,推导扰动最小要求。

假如我们有一个理想 N 位 ADC,满量程为 FS,量化步长为:

目标:引入一个扰动噪声 δ[n],使得量化误差变成非周期性、非相关(即白噪声样态)。

无扰动时的问题

当输入是:;且:

→ 输入在 M 点内重复 → 量化码重复 → 误差 e[n] 周期性,非白噪声!


加入扰动后建模

引入扰动后的输入为:

量化误差为:

我们希望 e[n] 近似为 白噪声过程(均值为 0,方差为 q²/12,且无自相关)。


扰动噪声如何“打断”周期性?

若扰动太小,x[n] + δ[n] 仍落在原来的同一个量化区间 → 输出不变

所以我们希望:

即:扰动足够大,使得大多数样本跨越量化边界


以概率模型建立判据

假设扰动 δ[n] 为均值 0、标准差 σ 的高斯白噪声

我们希望扰动使得:

比如设 p_thresh = 0.5,即希望有 50% 的概率扰动超过半个 LSB


解这个不等式:

查标准正态分布函数 的反函数:

当扰动噪声 RMS(标准差) σ > 0.74 × LSB 时,有超过 50% 的概率打断原有码字重复

我以上的模型是假设:每个点平均扰动 ≈ 跨区边界,也可以使用使扰动近似平均分布(均匀扰动),数学表达是,计算出RMS = q/√3 ≈ 0.577q

分析模型

数学条件

高斯扰动模型

均匀分布扰动

实际设计

峰值扰动 ≥ ±LSB,RMS ≥ 0.5~1 LSB

我这里也计算了不同位数ADC的LSB:

ADC 分辨率

1 LSB 幅度(FS=2Vpp)

建议扰动 RMS

8-bit

≈ 7.8 mV

≥ 4 mV RMS

12-bit

≈ 0.5 mV

≥ 0.3 mV RMS

16-bit

≈ 31 µV

≥ 20 µV RMS

建议扰动噪声采用均匀分布或白噪声,不要使用高频干扰或谐波信号作为扰动源。

“**未加扰动**”与“**加入 ±1 LSB 均匀分布扰动**”的 FFT 频谱对比结果
“**未加扰动**”与“**加入 ±1 LSB 均匀分布扰动**”的 FFT 频谱对比结果

展示了量化伪像被打散的实际效果

Without Dither:量化误差在频域呈现出周期性峰值(假谐波),即采样相关性伪像

With ±1 LSB Dither:这些峰值消失,频谱噪声分布更加均匀平滑,呈现真实 ADC 量化噪声特性

黄色曲线(未加扰动):

明显看到主频率信号(7Hz)之外,有周期性、等距的谐波峰值

这些不是真实谐波,而是由于:输入频率 = 采样率的整数比,从而导致 采样点重复,进而量化误差重复 ,形成假谐波,就是典型的相关性伪像现象

红色曲线(已加扰动 ±1 LSB):

主频率仍清晰存在(7Hz),原本的伪像“谐波”被打散为连续的背景噪声,频谱变得更接近理想 SNR 白噪声分布,说明扰动噪声起到了“去相关 + 去伪谐波”的作用。

扰动幅度达到 ±1 LSB(RMS ≈ 0.577 LSB)时,基本可打破相关性造成的频谱伪像

我想了一个办法,如果将这个扰动幅度逐级扫描,能不能定量评估 SNR 提升,就好像是扫频的原理。

**扰动幅度(以 LSB 为单位)** 与 **SNR(信噪比)** 之间的关系曲线
**扰动幅度(以 LSB 为单位)** 与 **SNR(信噪比)** 之间的关系曲线

**扰动幅度(以 LSB 为单位)** 与 **SNR(信噪比)** 之间的关系曲线

扰动幅度(LSB)

典型现象

SNR 变化趋势

0

无扰动 → 严重相关性伪像

SNR 被虚高(假 SFDR、假高峰)

0.1 ~ 0.5

扰动不足 → 伪像仍部分存在

SNR 波动,不稳定

0.7 ~ 1.0

打破相关性伪像、量化近似白噪声

SNR 最接近理论值

>1.2

扰动过大,开始破坏信号本身

SNR 下降,信号被噪声淹没

扰动 RMS ≈ 0.5~0.7 LSB(峰值 ±1 LSB)最合适:有效打散伪像又不会破坏信号质量

小扰动:无效打散,频谱仍伪造整洁

大扰动:信号失真,SNR 下降

加噪幅度建议在 ±1 LSB 峰值,或 ≥ 0.5 LSB RMS,这是最少可有效破除相关性的水平。

再看看扰动幅度(以 LSB 计)与 SNR、THD、SFDR、ENOB 四项关键 ADC 性能指标之间的关系:

扰动幅度(以 LSB 计)与 SNR、THD、SFDR、ENOB的关系
扰动幅度(以 LSB 计)与 SNR、THD、SFDR、ENOB的关系

扰动幅度(以 LSB 计)与 SNR、THD、SFDR、ENOB的关系

指标

随扰动幅度变化的趋势

SNR

- 在 0.5~1.0 LSB 时达到最优(有效打散伪像) - 太小扰动无效,太大扰动反而引入额外噪声

THD

- 原始量化造成严重谐波 - 扰动提升后 THD 明显改善

SFDR

- 未扰动时有高伪峰值 - ±1 LSB 附近扰动可极大提升 SFDR

ENOB

- 0~0.3 LSB 下偏离理论值(受相关性影响) - 达到 1 LSB 扰动时趋近理论 ENOB(约 7.8bit)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt
from numpy.fft import fft

# 模拟参数
fs = 1000            # 采样频率 Hz
N = 1024             # FFT 点数
f_in = fs * 7 / N    # 输入频率为 fs 的整数倍:造成相关性
t = np.arange(N) / fs

# ADC 模拟参数
n_bits = 8
q = 1 / (2 ** n_bits)       # LSB
v_fullscale = 1.0           # 满量程 ±1V
v_in = 0.9 * np.sin(2 * np.pi * f_in * t)  # 输入信号

# 加扰动前
x_no_dither = np.round(v_in / q) * q

# 加扰动后(添加 ±1 LSB 峰值均匀分布扰动)
dither = np.random.uniform(-q, q, size=N)
x_with_dither = np.round((v_in + dither) / q) * q

# FFT
def compute_fft(signal):
    fft_vals = fft(signal * np.hanning(N))
    fft_db = 20 * np.log10(np.abs(fft_vals[:N // 2]) / N + 1e-12)
    freqs = np.linspace(0, fs / 2, N // 2)
    return freqs, fft_db

freqs, fft_no_dither = compute_fft(x_no_dither)
_,     fft_with_dither = compute_fft(x_with_dither)

# 绘图(图例改为英文)
plt.figure(figsize=(10, 5))
plt.plot(freqs, fft_no_dither, label="Without Dither", linewidth=1.5)
plt.plot(freqs, fft_with_dither, label="With ±1 LSB Dither", linewidth=1.5)
plt.title("FFT Comparison: Correlation Artifacts vs Dithered Signal")
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude (dB)")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt
from numpy.fft import fft

# 模拟参数
fs = 1000
N = 1024
f_in = fs * 7 / N
t = np.arange(N) / fs

# ADC 参数
n_bits = 8
q = 1 / (2 ** n_bits)
v_in = 0.9 * np.sin(2 * np.pi * f_in * t)

# 定义扰动幅度列表(单位:LSB)
dither_levels = np.linspace(0, 1.5, 16)  # 01.5 LSB
snr_results = []

def calc_snr(signal, N):
    fft_vals = fft(signal * np.hanning(N))
    fft_mags = np.abs(fft_vals[:N // 2]) / N
    signal_bin = np.argmax(fft_mags)
    signal_power = fft_mags[signal_bin] ** 2
    noise_power = np.sum(fft_mags ** 2) - signal_power
    snr = 10 * np.log10(signal_power / noise_power + 1e-12)
    return snr

for dither_amp in dither_levels:
    dither = np.random.uniform(-dither_amp * q, dither_amp * q, size=N)
    x_dithered = np.round((v_in + dither) / q) * q
    snr = calc_snr(x_dithered, N)
    snr_results.append(snr)

# 绘图
plt.figure(figsize=(8, 5))
plt.plot(dither_levels, snr_results, marker='o')
plt.title("SNR vs Dither Amplitude")
plt.xlabel("Dither Amplitude (LSB Peak)")
plt.ylabel("SNR (dB)")
plt.grid(True)
plt.tight_layout()
plt.show()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np
import matplotlib.pyplot as plt
from numpy.fft import fft

# 模拟参数
fs = 1000
N = 1024
f_in = fs * 7 / N
t = np.arange(N) / fs
n_bits = 8
q = 1 / (2 ** n_bits)
v_in = 0.9 * np.sin(2 * np.pi * f_in * t)

# 扰动幅度列表
dither_levels = np.linspace(0, 1.5, 16)
results = {"Dither": [], "SNR": [], "THD": [], "SFDR": [], "ENOB": []}

def spectral_metrics(signal, N):
    win = np.hanning(N)
    signal_win = signal * win
    fft_vals = fft(signal_win)
    fft_mags = np.abs(fft_vals[:N // 2]) / (np.sum(win) / 2)
    fft_db = 20 * np.log10(fft_mags + 1e-20)

    signal_bin = np.argmax(fft_mags)
    signal_power = fft_mags[signal_bin] ** 2

    # 排除主频后计算 THD
    harmonics = []
    for h in range(2, 6):  # 2nd~5th harmonic
        bin_idx = h * signal_bin
        if bin_idx < len(fft_mags):
            harmonics.append(fft_mags[bin_idx] ** 2)
    thd = 10 * np.log10(sum(harmonics) / signal_power + 1e-20)

    # SFDR
    spurs = np.copy(fft_mags)
    spurs[signal_bin] = 0
    sfdr = 20 * np.log10(fft_mags[signal_bin] / (np.max(spurs) + 1e-20))

    # SNR(不含谐波,只含背景)
    total_power = np.sum(fft_mags ** 2)
    noise_power = total_power - signal_power - sum(harmonics)
    snr = 10 * np.log10(signal_power / noise_power + 1e-20)

    # ENOB
    enob = (snr - 1.76) / 6.02

    return snr, thd, sfdr, enob

# 模拟各扰动强度下的性能指标
for d_amp in dither_levels:
    dither = np.random.uniform(-d_amp * q, d_amp * q, size=N)
    x_dithered = np.round((v_in + dither) / q) * q
    snr, thd, sfdr, enob = spectral_metrics(x_dithered, N)
    results["Dither"].append(d_amp)
    results["SNR"].append(snr)
    results["THD"].append(thd)
    results["SFDR"].append(sfdr)
    results["ENOB"].append(enob)

# 绘图
plt.figure(figsize=(12, 8))

plt.subplot(2, 2, 1)
plt.plot(results["Dither"], results["SNR"], marker='o')
plt.title("SNR vs Dither Amplitude")
plt.xlabel("Dither Amplitude (LSB)")
plt.ylabel("SNR (dB)")
plt.grid(True)

plt.subplot(2, 2, 2)
plt.plot(results["Dither"], results["THD"], marker='o')
plt.title("THD vs Dither Amplitude")
plt.xlabel("Dither Amplitude (LSB)")
plt.ylabel("THD (dB)")
plt.grid(True)

plt.subplot(2, 2, 3)
plt.plot(results["Dither"], results["SFDR"], marker='o')
plt.title("SFDR vs Dither Amplitude")
plt.xlabel("Dither Amplitude (LSB)")
plt.ylabel("SFDR (dB)")
plt.grid(True)

plt.subplot(2, 2, 4)
plt.plot(results["Dither"], results["ENOB"], marker='o')
plt.title("ENOB vs Dither Amplitude")
plt.xlabel("Dither Amplitude (LSB)")
plt.ylabel("ENOB (bits)")
plt.grid(True)

plt.tight_layout()
plt.show()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云深之无迹 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要加噪声?我们不是最怕噪音了吗?
  • 文档中解决方法:加扰动噪声(Dithering)
  • 要加多大的扰动才能有效?
  • 无扰动时的问题
  • 加入扰动后建模
  • 扰动噪声如何“打断”周期性?
  • 以概率模型建立判据
    • 解这个不等式:
    • 黄色曲线(未加扰动):
    • 红色曲线(已加扰动 ±1 LSB):
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档