やりたいこと
Echo BaseはマイクとスピーカーをATOMに追加するモジュール。フィールドレコーディングとか楽しめそう、ということで録音して再生するアプリを作りたい。
チュートリアルを読もう
Echo Baseのチュートリアルでサンプルコードが公開されてます。これを改造して録音後も任意のタイミングで再生できるようにしてみる。
ライブラリでできること
録音
#define RECORD_SIZE (1024 * 96)
M5EchoBase echobase(I2S_NUM_0);
static uint8_t *buffer = nullptr;
// もろもろ初期化したらこれ一発でレコーディング
echobase.record(buffer, RECORD_SIZE);
再生
// これ呼べば再生開始
echobase.play(buffer, RECORD_SIZE);
ちょっと改造
このチュートリアルではATOMS3Rをクリックするとレコーディングを開始して即再生を行っている。とりあえずボタンのジェスチャーには長押しとかもあるので、長押しで録音開始、シングルクリックで再生するように改造してみる。
おまけでレコーディング開始前にスリーカウントのカウントダウンを挟んだ。即録音開始するとクリック音も録音されてしまうのでそれの回避策です。
あとレコーディングしていない状態では再生できないようにブロックしてある。いきなり再生するとノイズが再生されるからね。
修正後のコード
#include <M5Unified.h>
#include <Arduino.h>
#include <M5EchoBase.h>
#define RECORD_SIZE (1024 * 96)
M5EchoBase echobase(I2S_NUM_0);
static uint8_t *buffer = nullptr;
bool recorded = false;
void setup() {
M5.begin();
M5.Display.setFont(&fonts::FreeMonoBold9pt7b);
Serial.begin(115200);
echobase.init(16000, 38, 39, 7, 6, 5, 8, Wire);
echobase.setSpeakerVolume(60);
echobase.setMicGain(ES8311_MIC_GAIN_6DB);
buffer = (uint8_t *)malloc(RECORD_SIZE);
if (buffer == nullptr) {
while (true) {
M5.Display.println("Failed to allocate memory :(");
Serial.println("Failed to allocate memory :(");
delay(1000);
}
}
Serial.println("EchoBase ready, start recording and playing!");
M5.Display.println("Hold to Record & Play.");
M5.Display.println("Click to Playback.");
}
void loop() {
M5.update();
if (M5.BtnA.wasHold()) {
M5.Display.fillScreen(BLACK);
M5.Display.setCursor(0, 0);
M5.Display.println("Countdown");
// waiting 3 count
M5.Display.print("3, ");
delay(1000);
M5.Display.print("2, ");
delay(1000);
M5.Display.println("1");
delay(1000);
M5.Display.setTextColor(RED);
M5.Display.println("Recording");
// Recording
echobase.setMute(true);
delay(10);
M5.Display.setTextColor(WHITE);
echobase.record(buffer, RECORD_SIZE);
delay(100);
recorded = true;
M5.Display.println("Playing");
// Playing
echobase.setMute(false);
delay(10);
echobase.play(buffer, RECORD_SIZE);
delay(100);
M5.Display.println("Done");
} else if (M5.BtnA.wasClicked()) {
if (recorded) {
M5.Display.fillScreen(BLACK);
M5.Display.setCursor(0, 0);
M5.Display.println("Playing");
// Playing
echobase.setMute(false);
delay(10);
echobase.play(buffer, RECORD_SIZE);
delay(100);
M5.Display.println("Done");
}
}
}