ESP32ベースで **「2種類のヘッドフォン × 2種類の再生装置」** を客観的に比べるための、実行可能な設計・測定手順・サンプルコード・注意点をワンパッケージでお出しします。
長めですが、実際にその場で測定〜解析できるように具体的に書いてあります。足りないパーツや好みがあればそのまま始められます。
---
# 概要(やること)
1. 同一音源(ファイル)を用い、**再生装置A/B**から同じ信号を出力 → それぞれを**ヘッドフォン1/2**で聴く(組合せは計4パターン)。
2. ESP32システムで信号出力(I2S)と測定(マイク or 電圧検出)を自動化・切替制御・ログ取得。
3. 得られた波形から **周波数特性・THD(歪率)・S/N・SPL・位相差・遅延** を計算・比較。
4. ブラインド(ABX)テスト用にESP32で出力切替/ランダム化・ログを行い、主観テスト結果も記録。
---
# 必要ハードウェア(推奨)
最低限でESP32でできるように **実用と精度のバランス** を考慮した推奨構成:
必須:
* ESP32 開発ボード(I2S対応:例:ESP32 DevKitC)
* I2S出力用DAC/Codec(再生安定性とラインレベル出力のため)
* 例:PCM5102, ES9023, or I2S対応小型DACモジュール
* マイク入力(測定用)
* 低精度/簡易:I2S MEMSマイク(INMP441 / SPH0645)→ 簡単にESP32と繋げる
* 精密測定推奨:外部オーディオADC or USBオーディオ(PCM1808, PCM186x, TLV320系など)→ ダイナミックレンジが格段に向上
* ヘッドフォン用物理切替スイッチ(リレーまたは電子スイッチ → 例:小型リレー or ADG732のようなオーディオ用マルチプレクサ)
* 耳/ヘッドフォン測定用クージャ(簡易的には「人頭代替のカップ」に測定マイクを置く)またはインサートマイク(イヤーチップ測定)
* SPL計(スマホSPLアプリでも可。ただしキャリブレーション必要。理想は校正済み音圧計)
* 転送・記録用microSD(ESP32で結果ログを保存)またはシリアル/Wi-FiでPCへ送信
あると良い(精度向上):
* リファレンスマイク(校正済み)+校正器(94 dB / 1 kHz)
* 高精度外部ADC / オーディオインターフェース(THDやS/Nを厳密に取りたいなら必須)
* 耳型カップ(IEC 60268-7準拠の耳型クージャ) — プロ用途
> 注:ESP32 内蔵ADCは**音響測定にはノイズが多く、ダイナミックレンジが限られます**。THDや高SNR評価をしっかりやるなら外部I2SオーディオADC/Codecを使ってください(以降の手順は外部I2S ADC/マイクを使う前提で説明します)。
---
# 測定方針(どの指標をどう測るか)
1. **周波数特性(ヘッドフォン+再生系の合成)**
* 手順:定常スイープ(20Hz〜20kHz)または周期的ホワイトノイズを再生 → マイクで取得 → FFTで周波数特性(周波数ごとのゲイン)を算出。
* 出力:周波数対レベル(dB)グラフ、±X dBの平坦性評価。
2. **THD+N(歪率+ノイズ)**
* 手順:1 kHz正弦波を再生 → 録音 → 基本周波数と高調波成分をFFTで分解 → THD = sqrt(sum(2nd,3rd...)/fundamental) 。Nはノイズ成分を含めて計算(THD+N)。
* 注意:正確なTHD計測は高SNRかつ線形なADCが必要。
3. **S/N比**
* 手順:同じ基準信号レベル(例:−6 dBFSの1kHz)を再生 → 信号電力 / 無音時ノイズ電力を計算(dB)。
* 出力:dBで比較。
4. **位相/ステレオクロストーク**
* 手順:左チャネルに1kHz、右に無音 → 右出力のレベルを測ってクロストーク(dB)算出。左右入替で両方計測。
5. **SPL(実効音圧)**
* 手順:実際にヘッドフォンを装着する代替カップ(あるいは耳シミュレータ)にマイクを置き、再生音でSPL測定。再生装置の最大音圧到達性を比較。
6. **遅延(レイテンシ)**
* 手順:既知のトリガを同時に出して、再生波形到達時刻を検出 → レイテンシ算出(オーディオ同期が必要)。
7. **主観(ABX)**
* ESP32でランダムにA/B切替→Xを当てるテストを自動化。結果はログに保存して統計的検定を行う。
---
# 実験配線(概念)
```
音源ファイル(SD/Flash/ネット) ──> ESP32 (I2S out) ──> 再生装置A/B(外部アンプ等)
│
└─> ヘッドフォン切替:リレーで道を切替
ヘッドフォン (on-ear/イヤーカップ) ── マイク(インサート or カップ中) ──> I2S ADC / I2S MIC ──> ESP32(録音)
```
* ESP32は **I2Sで再生**(DACモジュールへ)し、同時に **I2Sマイク/外部オーディオADCで録音** します。
* 切替(ヘッドフォンや再生装置の選択)はESP32のGPIOでリレー/電子スイッチを制御します。
---
1. マイク校正:校正器(94 dB@1 kHz)でマイクを校正 → マイク感度係数を得る。スマホアプリ使用時も基準トーンで校正。
2. レベル合わせ:同一音圧(e.g. 85 dB SPL)を基準に、DAC出力やアンプゲインを調整して測定開始点を統一。
3. ケーブル/コネクタ:接触抵抗や引き回しで差が出るので同じ配線長・同じコネクタを使う。
---
# ESP32側:実装概要(主要ポイント)
* 再生:I2SでPCMデータを送る(ファイル再生 or 内蔵生生成信号)
* 録音:I2Sマイク/外部ADCから同一サンプリングレートでサンプリング(48 kHz 推奨)
* 切替:GPIO制御でリレーを動かし、出力先(装置A/B、ヘッドフォン1/2)を選ぶ
* 測定処理:FFT(window付き)、THD計算、SNR算出、保存(microSD/Wi-Fi)
* ABX:ランダム化、ユーザー操作で回答登録、CSV保存
以下に **Arduino (ESP32) のサンプルコード骨子** を示します(主要処理のみ)。実機ではライブラリの導入・I2S設定・エラーチェック等が必要です。
---
## サンプル:I2Sで正弦波を再生し、I2Sマイクで録音 → FFTでスペクトル表示(骨子)
(実装要点のみ。実際はライブラリ追加、I2Sピン設定、エラーチェックを行ってください)
```cpp
// 必要ライブラリの例(Arduino環境)
#include <driver/i2s.h>
#include <arduinoFFT.h>
// I2S 設定(再生 & 録音ともに同じサンプリング周波数に揃える)
#define SAMPLE_RATE 48000
#define I2S_NUM_OUT I2S_NUM_0
#define I2S_NUM_IN I2S_NUM_1
#define FFT_SIZE 4096 // 2^n
arduinoFFT FFT;
double vReal[FFT_SIZE];
double vImag[FFT_SIZE];
void setupI2Sout() {
// I2S出力の初期化:使用するDAC/Codecに応じてフォーマットを設定
// ...
}
void setupI2Sin() {
// I2S入力(I2Sマイク or ADC)
// ...
}
void generateSineBlock(int16_t* buffer, int blockSize, double freq, int sampleRate) {
static double phase = 0;
double phaseInc = 2.0 * M_PI * freq / sampleRate;
for (int i=0;i<blockSize;i++) {
buffer[i] = (int16_t)(32767 * 0.7 * sin(phase)); // 0.7 to avoid clipping
phase += phaseInc;
if (phase > 2*M_PI) phase -= 2*M_PI;
}
}
void loopPlaySineAndRecord() {
const int blockSize = 256;
static int16_t outBuf[256];
int16_t inBuf[256];
// 1) 出力(例:1kHz)
generateSineBlock(outBuf, blockSize, 1000.0, SAMPLE_RATE);
// write to I2S out
size_t bytes_written;
i2s_write(I2S_NUM_OUT, outBuf, blockSize * sizeof(int16_t), &bytes_written, portMAX_DELAY);
// 2) 録音
size_t bytes_read;
i2s_read(I2S_NUM_IN, inBuf, blockSize * sizeof(int16_t), &bytes_read, portMAX_DELAY);
// 3) バッファをFFT用配列に入れる(例、4096を満たしてからFFT)
for (int i = 0; i < blockSize; i++) {
// 簡易:16-bit -> double
vReal[i] = (double)inBuf[i];
vImag[i] = 0.0;
}
// ... accumulate until FFT_SIZE samples collected
}
// FFT解析・THD算出の流れ(pseudo)
void analyzeFFTAndComputeTHD() {
FFT.Windowing(vReal, FFT_SIZE, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, FFT_SIZE, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, FFT_SIZE);
// find fundamental bin, sum harmonic bins, compute THD
// THD = sqrt(sum(harmonics^2)) / fundamental
}
```
> 実装注記:上は概念コードです。実機では I2S の設定(ピン、フォーマット、bits_per_sample)やバッファ同期、サンプル数の扱い、ウィンドウ処理、検出アルゴリズムをきちんと行ってください。
---
# 信号設計(測定用信号)
1. **正弦波(1 kHz)**:THD測定、SNR測定
2. **スイープ(20 Hz → 20 kHz, 10〜30秒)**:周波数特性
3. **定常ホワイトノイズ or MLS(擬似白色列)**:周波数応答、IR抽出
4. **短いインパルス(クリック)**:遅延測定・インパルス応答
5. **実音楽(参照曲)**:主観比較・最大出力の実地確認
---
# THD 算出(数式) — サンプル手順
1. FFTで周波数スペクトルを得る(窓関数を適用)
2. 基本周波数 bin の振幅を A1 とする
3. 2次・3次・・・k次までの各高調波振幅 Ak を取り出す(必要なら周辺binを合算)
4. THD = sqrt(sum_{n=2..N}(Ak^2)) / A1
5. THD% = THD * 100
6. THD+N は、全帯域パワーからA1^2と高調波分を除いた部分をノイズと見なして計算
> 精度注意:FFT窓幅・周波数分解能・スレッショルド・窓漏れ対策で結果が大きく変わります。窓関数はHann/Hammingを推奨。基本周波数がFFTの正確なbinに乗るように信号長を調整(同期検波的手法)できれば精度向上。
---
# ABX(ブラインド)テストの自動化(ESP32で)
* ESP32は再生装置/ヘッドフォンの組合せを**ランダム化して切替**(GPIOリレー) → ユーザーに「A or B or X」を聞かせ、ボタンで回答を登録。
* ログには「試行番号, ランダムシード, 実際の選択(A/B), ユーザ回答, 時刻」保存。PCで統計解析(カイ二乗検定等)を行い、有意差を検定。
簡単なワークフロー:
1. 試行を N 回(例:20回)実施
2. 各試行で X は A or B のいずれか(ESP32でランダム決定)
3. ユーザーがXの正体を当てる → 結果ログ
4. 解析:正答率を計算、確率的有意差を検定(binomial test)
---
# データの保存とレポート
* CSVフォーマット例(測定ログ):
```
timestamp,setup_id,signal,repeat,device,headphone,SPL_dB,THD_percent,SNR_dB,notes
2025-11-03T01:23:45Z,setup1,sine1k,1,playA,hp1,86.2,0.12,84.5,"ok"
```
* レポート(PDF/Word)にグラフ(周波数応答、THD棒グラフ、SPL比較、ABX結果)を埋め込むと分かりやすいです。ESP32からWi-Fiで取得→PCで解析→レポート生成が一番楽。
---
# 実行上の注意・限界
* **ESP32内蔵ADCは測定精度が低い**(ノイズ・非線形が大きい)。必ず外部オーディオADC/CodecかI2Sマイクを使うこと。
* THDやS/N比の厳密比較は測定チェーン全体(マイク・ADC・アンプ)での誤差に依存します。比較は **同一チェーン** で行い、チェーンの方が機器差より小さいことを確認してください。
* ヘッドフォンの装着条件(位置・密閉度)でSPLやレスポンスはかなり変わります。できるだけ再現性を担保する(同じクランプ力のヘッドバンド、同じ位置)こと。
* 人間の聴覚は周波数帯域や音量により感度が異なるため、客観値(測定)と主観(ABX)を両方残してください。
---
# すぐに使えるチェックリスト(作業順)
1. 機材を揃える(I2S DAC、I2S MIC、リレー、SPL計/校正マイク、microSD)
2. ハード配線(再生→装置A/B、切替リレー、ヘッドフォン)を構築
3. マイクの校正(校正トーンで感度合わせ)
4. ESP32で1kHz正弦を再生→録音して波形確認(クリッピングの有無)
5. スイープを再生→録音→周波数レスポンス取得(グラフ保存)
6. THD測定(1kHz)→複数レベルで測定(低域〜高域)
7. SPL最大測定(安全上の注意:長時間大音量は不可)
8. ABXテスト(ユーザー数と試行数を確保)
9. データ整理→比較表・グラフ作成→結論
---
# もし欲しければ(次に出せる成果)
* ESP32用の **完全なArduinoスケッチ(I2S再生+I2S録音+FFT+THD計算+リレー切替+microSD保存)** を作成して渡します。
* PC側での **解析用Pythonスクリプト**(CSV読み込み→周波数応答グラフ、THD計算、ABX統計)を用意します。
* 測定シート(Excel/CSVテンプレート)とレポート雛形(Word/PDFテンプレ)を用意します。
どれを優先しましょうか?
1. まずは「ESP32の完全なスケッチ」を出す(自動化重視)
2. 「PC用解析スクリプト(Python)」を先に出す(データ解析重視)
3. 両方まとめて欲しい(ワンパック)
ご希望を教えてください。すぐにコード/スクリプトを出します(現物で実行できるレベルのものを提供します)。