デジタル信号処理におけるFFTスペクトル解析と性能評価


#### **概要**
本記事では、**デジタル信号処理（DSP）におけるFFT（高速フーリエ変換）を用いたスペクトル解析と、ADC（アナログ-デジタル変換）システムの性能指標であるSNDR、ENOB、SFDRの計算方法**について解説します。  
また、Pythonを用いた具体的な実装コードを紹介し、取得した信号のサンプリング、FFTによる周波数成分の解析、性能指標の算出方法を説明します。

---

## **1. 解析対象の信号**
まず、`time_data` と `signal_data` を含むCSVファイルを読み込み、時系列信号を取得します。  
この信号には、オフセット補正を行い、特定のサンプリング周波数（1MSPS: 1メガサンプル/秒）でサンプリングを行います。

```python
# CSVファイルのアップロード
uploaded = files.upload()
file_name = list(uploaded.keys())[0]
data = pd.read_csv(file_name)

# 信号データの取得
time_data = data['time_data'].to_numpy()
signal_data = data['signal_data'].to_numpy()
```

アップロードした信号データは、以下のように可視化されます。

```python
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data, label="Original Signal")
plt.title('Original Signal vs Time')
plt.xlabel('Time [s]')
plt.ylabel('Signal')
plt.grid(True)
plt.legend()
plt.show()
```

### **オフセット補正**
測定された信号にはオフセットが含まれる可能性があるため、オフセット補正を行います。本コードでは `signal_data - 8` の処理を行い、信号の基準をゼロに近づけています。

```python
signal_data_modified = signal_data - 8
```

補正後の信号をプロットして確認します。

```python
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data_modified, label="Modified Signal", color='r')
plt.title('Modified Signal vs Time')
plt.xlabel('Time [s]')
plt.ylabel('Modified Signal')
plt.grid(True)
plt.legend()
plt.show()
```

---

## **2. クロック信号とサンプリング**
### **クロック信号の設定**
デジタル回路では、クロック信号を用いて信号のサンプリングを行います。本コードでは、1MHz（1 MSPS）のサンプリングレートで遅延要素 `delay_element = 0.00000028` を考慮しながら、サンプリング時刻を生成しています。

```python
simulation_time = 0.000512  # シミュレーション時間 (512 µs)
sampling_rate = 1e6  # サンプリング周波数 (1 MSPS)
delay_element = 0.00000028  # 遅れ要素 (280 ns)

# サンプリング時刻の作成
sampled_time = np.arange(delay_element, simulation_time, 1 / sampling_rate)
```

### **信号のサンプリング**
補間を用いて、作成した `sampled_time` に対応する信号値を取得します。

```python
sampled_signal = np.interp(sampled_time, time_data, signal_data_modified)
```

サンプリングした信号を可視化し、元の信号との比較を行います。

```python
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data_modified, label="Modified Signal", color='r', alpha=0.5)
plt.scatter(sampled_time, sampled_signal, color='b', label="Sampled Signal", zorder=3)
plt.title('Sampled Signal from delay_element to Simulation Time')
plt.xlabel('Time [s]')
plt.ylabel('Modified Signal')
plt.grid(True)
plt.legend()
plt.show()
```

また、最初の50点のサンプリング結果を表示します。

```python
print("First 50 Sampled Points (Time [s] - Signal):")
for i in range(min(50, len(sampled_time))):
    print(f"{sampled_time[i]:.9f} s - {sampled_signal[i]:.6f}")
```

---

## **3. FFT（高速フーリエ変換）を用いたスペクトル解析**
FFTを用いて、サンプリングした信号の周波数スペクトルを解析します。

```python
N = len(sampled_signal)
fs = sampling_rate  # サンプリング周波数
freqs = np.fft.fftfreq(N, d=1/fs)[:N//2]  # 正の周波数成分のみ取得
spectrum = np.abs(fft(sampled_signal)[:N//2])  # FFTの絶対値

# 最大値を0 dBに正規化
spectrum_magnitude_db = 20 * np.log10(spectrum / np.max(spectrum))
```

### **FFTスペクトルのプロット**
```python
plt.figure(figsize=(10, 4))
plt.plot(freqs / fs, spectrum_magnitude_db, label='FFT (Normalized)')
plt.axhline(y=0, color='r', linestyle='--', label='0 dB Reference')
plt.xlabel('Normalized Frequency (f/fs)')
plt.ylabel('Magnitude [dB]')
plt.title('FFT Spectrum (0 dB = max amplitude)')
plt.legend()
plt.grid(True)
plt.show()
```

---

## **4. ADCの性能評価指標（SNDR, ENOB, SFDR）**
ADC（アナログ-デジタル変換）の評価には、以下の指標が重要です。

- **SNDR（Signal-to-Noise and Distortion Ratio）**  
  - 信号成分のパワーとノイズ+歪成分のパワーの比
- **ENOB（Effective Number of Bits）**  
  - SNDRを基にしたADCの有効ビット数
- **SFDR（Spurious-Free Dynamic Range）**  
  - 最大信号成分とスプリアス歪成分の比

```python
signal_power = np.max(spectrum)**2  # 信号成分のパワー
noise_power = np.sum(spectrum**2) - signal_power  # ノイズ+歪成分のパワー

SNDR = 10 * np.log10(signal_power / noise_power)  # SNDR計算
ENOB = (SNDR - 1.76) / 6.02  # ENOB計算

# SFDRの計算
spurious_spectrum = spectrum.copy()
spurious_spectrum[np.argmax(spectrum)] = 0  # 最大信号成分を除外
SFDR = 20 * np.log10(np.max(spectrum) / np.max(spurious_spectrum))  # SFDR計算
```

計算結果を表示します。

```python
print(f"Simulation Time: {simulation_time:.6f} s")
print(f"SNDR: {SNDR:.2f} dB")
print(f"ENOB: {ENOB:.2f} bits")
print(f"SFDR: {SFDR:.2f} dB")
```

---

## **5. まとめ**
本記事では、**サンプリングした信号のFFT解析とADCの性能評価をPythonで実装する方法** を紹介しました。  
特に、**SNDR, ENOB, SFDRの計算** を通じて、ADCの性能を評価することが可能になります。  
本手法を活用することで、実際のADCの性能を測定し、最適なデータ取得・処理方法を検討できます。

今後の応用として、**ウィンドウ関数の適用やノイズ除去フィルタの設計** などの手法を導入することで、より精度の高いスペクトル解析が可能になります。