🎙️

Teensy 4.1にPCM1802で音声入力→PCM5102A差動出力

2025/02/27に公開

前回は、PCM5102Aを用いた音声の出力方法を紹介しましたが、今回はその応用として、PCM1802で音声を入力し、2つのPCM5102Aを組み合わせてステレオの差動(バランス)出力をする方法を解説します。
https://zenn.dev/saisana299/articles/9924e809e87193

PCM1802で音声入力


PCM1802は最大24bit/96kHzでステレオのオーディオデータを取り込めるADCです。
TeensyではオーディオライブラリにあるAudioInputI2Sを使って音声を取り込むことができます。


PCM1802のデータシート より
※PCM1802をI2Sモードで使用するにはFMT1をLOW、FMT0をHIGHにする必要があります。

使用したボードと注意点

ADCの動作確認をするためにAliExpressでPCM1802を搭載したボードを購入しました。
https://ja.aliexpress.com/item/1005006412873984.html
このボードを使用する場合は、配線を少し弄る必要があります。
以下のページで解説されていますが、FMT0のパッドと3.3Vを配線して接続する必要があります。
https://www.pjrc.com/pcm1802-breakout-board-needs-hack/

PCM1802を配線

PCM1802とTeensy 4.1を接続します。
Teensy 4.1のピン配置図を参考に各ピンを接続してください。

PCM1802 Teensy 4.1 Teensy側ピン番号
SCK MCLK1 23
POW 3.3V 3V
LRCK LRCLK1 20
FSY 3.3V 3V
BCK BCLK1 21
DOUT IN1 8
GND GND G
3.3V 3.3V 3V
+5V 5V 5V

PCM5102Aを2つ使って差動出力

PCM5102Aはシングルエンド出力、このまま音声端子に接続する場合アンバランス接続となるため、ノイズなどの影響を受けやすくなります。
1つのPCM5102Aを左チャンネル用、もう1つを右チャンネル用として、それぞれで通常の信号と位相を反転させた信号を送ることでノイズを除去することが可能です。
※参考:PCM5102を調べてみよう!の巻き。
今回はソフトウェア側で非反転のデータと反転させたデータを用意してDACに送信します。

使用したボードと注意点

Youmile PCM5102 DAC GY-PCM5102
AmazonにあるPCM5102Aボードを使用しました。
このボードを使用する際、以下のようにパッドがはんだ付けされていない場合は、同じようにはんだ付けしてください。

PCM5102Aを配線

差動構成のため、今回はAudioOutputI2SQuadを使用します。
2つのPCM5102AとPCM1802は共通のBCLK、LRCKピンを使います。
以下のようにTeensy 4.1と接続します。

Lチャンネル用

Teensy 4.1 Teensy側ピン番号 PCM5102A
GND G SCK
BCLK 21 BCK
TX (ch 1+2) 7 DIN
LRCLK 20 LCK
GND G GND
3.3V 3V VIN

Rチャンネル用

Teensy 4.1 Teensy側ピン番号 PCM5102A
GND G SCK
BCLK 21 BCK
TX (ch 3+4) 32 DIN
LRCLK 20 LCK
GND G GND
3.3V 3V VIN

コード

PCM1802→Teensy4.1→PCM5102A差動 となるようにコードを書いていきます。
プログラムを図で表すと以下のようになります。

Input→RecordQueue→反転処理→PlayQueue→Output

プログラム全体

#include <Arduino.h>
#include <Audio.h>

// --------------
// Audio Object
// --------------
// I2S 入力 -> RecordQueue(Left, Right)
AudioInputI2S      i2s;   // BCLK=21, MCLK=23, LRCLK=20, RX=8
AudioRecordQueue   rec_L; // L
AudioRecordQueue   rec_R; // R

// I2SQuad 出力 (4ch: L+, L-, R+, R-)
AudioOutputI2SQuad i2s_quad;
AudioPlayQueue     queue_L;  // L+
AudioPlayQueue     queue_LM; // L- (L の符号反転)
AudioPlayQueue     queue_R;  // R+
AudioPlayQueue     queue_RM; // R- (R の符号反転)

// --------------
// Audio Connection
// --------------
// I2S 入力 -> RecordQueue(Left, Right)
AudioConnection patchCord1(i2s, 0, rec_L, 0);
AudioConnection patchCord2(i2s, 1, rec_R, 0);

// PlayQueue -> I2SQuad 出力  (チャネル順: 0=L+, 1=L-, 2=R+, 3=R-)
AudioConnection patchCord3(queue_L,   0, i2s_quad, 0);
AudioConnection patchCord4(queue_LM,  0, i2s_quad, 1);
AudioConnection patchCord5(queue_R,   0, i2s_quad, 2);
AudioConnection patchCord6(queue_RM,  0, i2s_quad, 3);

// --------------
// Audio Buffer
// --------------
// 1ブロック(=128サンプル)単位で作業するための配列
static const int BLOCK_SIZE = AUDIO_BLOCK_SAMPLES; // 通常128
int16_t samples_L [BLOCK_SIZE];
int16_t samples_LM[BLOCK_SIZE];
int16_t samples_R [BLOCK_SIZE];
int16_t samples_RM[BLOCK_SIZE];

inline int16_t negation(int16_t value) {
  return (value == INT16_MIN) ? INT16_MAX : -value;
}

void setup() {
  // Audio処理用メモリの割り当て (必要な量を確保 100は適当)
  AudioMemory(100);

  // RecordQueue を開始 (オーディオ入力の取り込みスタート)
  rec_L.begin();
  rec_R.begin();
}

void loop() {
  // L, R それぞれのキューにオーディオデータが溜まっているか確認
  if ((rec_L.available() > 0) && (rec_R.available() > 0)) {
    // それぞれ1ブロック(128サンプル)を取り出す
    int16_t *blockL = rec_L.readBuffer();
    int16_t *blockR = rec_R.readBuffer();

    if (blockL != nullptr && blockR != nullptr) {
      // blockL, blockR に各128サンプルの音声データがある
      // 符号反転 (L-, R-) や必要な処理を行い、別バッファへコピー
      for (int i = 0; i < BLOCK_SIZE; i++) {
        samples_L [i] = blockL[i];           // L+
        samples_LM[i] = negation(blockL[i]); // L- (反転)
        samples_R [i] = blockR[i];           // R+
        samples_RM[i] = negation(blockR[i]); // R- (反転)
      }

      // PlayQueue へ書き込み → Quad 出力へ
      queue_L.play(samples_L,   BLOCK_SIZE);
      queue_LM.play(samples_LM, BLOCK_SIZE);
      queue_R.play(samples_R,   BLOCK_SIZE);
      queue_RM.play(samples_RM, BLOCK_SIZE);
    }

    // 使い終わったらバッファを解放 (重要)
    rec_L.freeBuffer();
    rec_R.freeBuffer();
  }
}

実行してみる

シンプルな三角波を入力してみました。
KORGのオシロスコープで確認すると、正しくバランス出力ができていることが確認できます。

右チャンネルの出力 非反転の位相と反転の位相になっている

音楽をPCM1802に入力してPCM5102Aから出力したものを録音してみました。
16bit/44.1kHzですが、割と良い音に聞こえます。
https://youtu.be/gpcYUnIzHCI?si=48lKdz9OkqF_4_p2

Discussion