やりたいこと
以前Atomic Echo Baseを使って録音する簡単なサンプルの記事を書いた。
でもいつからかな?このコードが動かなくなっていた。シリアルモニタを見ると以下のログが延々でて起動しないのであった。
echo base i2s(legacy): CONFLICT! The new i2s driver can't work along with the legacy i2s driver
もう#include <M5EchoBase.h>って書いただけのスケッチでもこれ。
チャッピーに聞くとM5EchoBase.hが、
#include "driver/i2s.h"
しちょるけん、書き換えないとぶつかるよ、と。
直した
M5Unifiedのソースを読むとconfigにexternal_speaker.atomic_echoとかあるじゃないですか。こんな感じで初期化してあげればAtomic Echo BaseがM5Unifiedだけで使えるんじゃないかな?と思って以前のサンプルコードを書き換えてみたらちゃんと動いた。
コンフィグ設定
auto config = M5.config();
config.external_speaker.atomic_echo = true;
M5.begin(config);
録音と再生
録音
Mic_Class
bool record(int16_t* rec_data, size_t array_len, uint32_t sample_rate, bool stereo = false);
再生
Speaker_Class
bool playRaw(const int8_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false);
サンプル
ボタンホールドで録音開始(スリーカウント後)、ボタンクリックで録音データの再生するサンプル。
サンプルコード
#include <M5Unified.h>
#define RECORD_SIZE (1024 * 96)
bool recorded = false;
static constexpr const size_t record_samplerate = 16000;
static int16_t *rec_data;
void setup() {
// put your setup code here, to run once:
auto config = M5.config();
config.external_speaker.atomic_echo = true;
M5.begin(config);
Serial.begin(115200);
M5.Display.setFont(&fonts::FreeMonoBold9pt7b);
rec_data = (typeof(rec_data))heap_caps_malloc(RECORD_SIZE * sizeof(int16_t), MALLOC_CAP_8BIT);
memset(rec_data, 0 , RECORD_SIZE * sizeof(int16_t));
M5.Speaker.setVolume(200);
M5.Speaker.end();
M5.Mic.begin();
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
M5.Speaker.end();
delay(10);
M5.Display.setTextColor(WHITE);
memset(rec_data, 0 , RECORD_SIZE * sizeof(int16_t));
recorded = M5.Mic.record(rec_data, RECORD_SIZE, record_samplerate, false);
delay(100);
while (M5.Mic.isRecording()) {
M5.delay(1);
M5.update();
}
recorded = true;
M5.Display.println("Playing");
// Playing
M5.Mic.end();
M5.Speaker.begin();
delay(10);
M5.Speaker.playRaw(rec_data, RECORD_SIZE, record_samplerate, false, 1, 0);
while (M5.Speaker.isPlaying()) {
M5.delay(1);
M5.update();
}
delay(100);
M5.Speaker.end();
M5.Mic.begin();
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
M5.Mic.end();
M5.Speaker.end();
M5.Speaker.begin();
delay(10);
M5.Speaker.playRaw(rec_data, RECORD_SIZE, record_samplerate, false, 1, 0);
while (M5.Speaker.isPlaying()) {
M5.delay(1);
M5.update();
}
delay(100);
M5.Mic.begin();
M5.Display.println("Done");
}
}
}