pdf-icon

Arduino Quick Start

2. Devices & Examples

6. Applications

Cardputer Mic

APIs and example programs related to the Cardputer Mic, applicable to Cardputer and Cardputer-Adv.

Example Program

Compilation Requirements

  • M5Stack board manager version >= 3.2.2
  • Board option = M5Cardputer
  • M5Cardputer library version >= 1.1.0
  • M5Unified library version >= 0.2.8
  • M5GFX library version >= 0.2.10
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
#include <M5Cardputer.h>

static constexpr const size_t record_number = 256;
static constexpr const size_t record_length = 240;
static constexpr const size_t record_size = record_number * record_length;
static constexpr const size_t record_samplerate = 17000;
static int16_t prev_y[record_length];
static int16_t prev_h[record_length];
static size_t rec_record_idx = 2;
static size_t draw_record_idx = 0;
static int16_t *rec_data;

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

  M5Cardputer.Display.startWrite();
  M5Cardputer.Display.setRotation(1);
  M5Cardputer.Display.setTextDatum(top_center);
  M5Cardputer.Display.setTextColor(WHITE);
  M5Cardputer.Display.setFont(&fonts::FreeSansBoldOblique12pt7b);

  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));
  M5Cardputer.Speaker.setVolume(255);

  // Turn off the speaker, because the microphone and speaker cannot be used at the same time.
  M5Cardputer.Speaker.end();
  M5Cardputer.Mic.begin();
  M5Cardputer.Display.fillCircle(70, 15, 8, RED);
  M5Cardputer.Display.drawString("REC", 120, 3);
}

void loop(void) {
  M5Cardputer.update();

  if (M5Cardputer.Mic.isEnabled()) {
    static constexpr int shift = 6;
    auto data = &rec_data[rec_record_idx * record_length];
    if (M5Cardputer.Mic.record(data, record_length, record_samplerate)) {
      data = &rec_data[draw_record_idx * record_length];

      int32_t w = M5Cardputer.Display.width();
      if (w > record_length - 1) {
        w = record_length - 1;
      }
      for (int32_t x = 0; x < w; ++x) {
        M5Cardputer.Display.writeFastVLine(x, prev_y[x], prev_h[x], TFT_BLACK);
        int32_t y1 = (data[x] >> shift);
        int32_t y2 = (data[x + 1] >> shift);
        if (y1 > y2) {
          int32_t tmp = y1;
          y1 = y2;
          y2 = tmp;
        }
        int32_t y = ((M5Cardputer.Display.height()) >> 1) + y1;
        int32_t h = ((M5Cardputer.Display.height()) >> 1) + y2 + 1 - y;
        prev_y[x] = y;
        prev_h[x] = h;
        M5Cardputer.Display.writeFastVLine(x, prev_y[x], prev_h[x], WHITE);
      }

      M5Cardputer.Display.display();
      M5Cardputer.Display.fillCircle(70, 15, 8, RED);
      M5Cardputer.Display.drawString("REC", 120, 3);
      if (++draw_record_idx >= record_number) {
        draw_record_idx = 0;
      }
      if (++rec_record_idx >= record_number) {
        rec_record_idx = 0;
      }
    }
  }

  if (M5Cardputer.BtnA.wasHold()) {
    auto cfg = M5Cardputer.Mic.config();
    cfg.noise_filter_level = (cfg.noise_filter_level + 8) & 255;
    M5Cardputer.Mic.config(cfg);
    M5Cardputer.Display.clear();
    M5Cardputer.Display.fillCircle(70, 15, 8, GREEN);
    M5Cardputer.Display.drawString("NF:" + String(cfg.noise_filter_level), 120, 3);

  } else if (M5Cardputer.BtnA.wasClicked()) {
    if (M5Cardputer.Speaker.isEnabled()) {
      M5Cardputer.Display.clear();
      while (M5Cardputer.Mic.isRecording()) {
        delay(1);
      }
      // Turn off the microphone, because the microphone and speaker cannot be used at the same time.
      M5Cardputer.Mic.end();
      M5Cardputer.Speaker.begin();

      M5Cardputer.Display.fillTriangle(70 - 8, 15 - 8, 70 - 8, 15 + 8, 70 + 8, 15, 0x1c9f);
      M5Cardputer.Display.drawString("PLAY", 120, 3);
      int start_pos = rec_record_idx * record_length;
      if (start_pos < record_size) {
        M5Cardputer.Speaker.playRaw(&rec_data[start_pos], record_size - start_pos, record_samplerate, false, 1, 0);
      }
      if (start_pos > 0) {
        M5Cardputer.Speaker.playRaw(rec_data, start_pos, record_samplerate, false, 1, 0);
      }
      do {
        delay(1);
        M5Cardputer.update();
      } while (M5Cardputer.Speaker.isPlaying());

      // Turn off the speaker, because the microphone and speaker cannot be used at the same time.
      M5Cardputer.Speaker.end();
      M5Cardputer.Mic.begin();

      M5Cardputer.Display.clear();
      M5Cardputer.Display.fillCircle(70, 15, 8, RED);
      M5Cardputer.Display.drawString("REC", 120, 3);
    }
  }
}

This program displays the waveform of the sound collected by the microphone on the device screen, and buffers the recording of the last few seconds. By pressing the G0 button (BtnA) on the top side, the device will replay the most recent few seconds of recording (the playback volume will be lower than the actual volume).

API

The M5Cardputer library is built on top of the M5Unified library. The microphone driver uses the Mic_Class from the M5Unified library. For more detailed APIs, please refer to the following documentation:

On This Page