M5Stick2 PlusC で集音し、音声波形を表示する

こう書く。

#include <M5Unified.h>

// 画面の横幅に合わせてサンプル数を設定 (StickC Plus2は横向きで240px)
const int32_t record_length = 240; 
const uint32_t record_samplerate = 16000; // 16kHzサンプリング

int16_t* rec_data; // 音声データを格納するバッファへのポインタ
int32_t prev_y[record_length]; // 前回の描画位置を記憶する配列(チラつき防止用)

void setup() {
    auto cfg = M5.config();
    M5.begin(cfg);

    // 画面を横向きに設定
    MALLOC_CAP_8BIT;
    M5.Display.setRotation(3); 
    M5.Display.fillScreen(TFT_BLACK);

    // 録音用のメモリ領域(バッファ)を確保
    rec_data = (int16_t*)heap_caps_malloc(record_length * sizeof(int16_t), MALLOC_CAP_8BIT);
    
    if (rec_data == nullptr) {
        M5.Display.println("Memory allocation failed!");
        while (1) delay(10);
    }

    // 内蔵マイクの初期化と開始
    M5.Mic.begin();

    // 過去の描画位置配列を画面中央(y=67)で初期化
    for (int i = 0; i < record_length; i++) {
        prev_y[i] = M5.Display.height() / 2;
    }
}

void loop() {
    M5.update();

    // マイクからデータを record_length 分だけ録音
    if (M5.Mic.record(rec_data, record_length, record_samplerate)) {
        
        int32_t mid_y = M5.Display.height() / 2; // 画面の中央

        // 最初の点のy座標を計算しておく(ループの外で1点目を作っておく)
        int32_t next_y = mid_y + (rec_data[0] >> 8);
        if (next_y < 0) next_y = 0;
        if (next_y >= M5.Display.height()) next_y = M5.Display.height() - 1;

        int32_t current_y = next_y; // 今回のスタート点
        int32_t last_current_y = current_y; 

        // 1ピクセルずつ右に進みながら、前のピクセルと線を結ぶ
        for (int32_t x = 1; x < M5.Display.width(); ++x) {
            
            // ① 前回の古い「線」を黒で消す (x-1 から x への線)
            M5.Display.drawLine(x - 1, prev_y[x - 1], x, prev_y[x], TFT_BLACK);

            // ② 次の点のy座標を計算
            next_y = mid_y + (rec_data[x] >> 8);
            if (next_y < 0) next_y = 0;
            if (next_y >= M5.Display.height()) next_y = M5.Display.height() - 1;

            // ③ 新しい「線」を緑色(TFT_GREEN)で描画してみる (オシロスコープ風)
            M5.Display.drawLine(x - 1, current_y, x, next_y, TFT_GREEN);

            // ④ 次のループのために、今回のスタート地点のy座標を記憶
            // (同時に、次回の「消去用」としてprev_yにも保存)
            prev_y[x - 1] = current_y;
            current_y = next_y;
        }
        
        // ループが終わったら、最後の1点分の履歴も保存
        prev_y[M5.Display.width() - 1] = current_y;
    }
}