Wio Terminal本体のみでMP3を鳴らす


2021/11/23公開

概要
Wio Terminal本体のSDカードに保存されたMP3を本体によるデコードで鳴らすTipsです。
Wio TerminalでMP3を再生する方法についてググってみたところGrove MP3を制御して鳴らす例はありましたが、
本体のみで完結している例はありませんでしたので、ここに検証した結果を残しておきたいと思います。

解説
MP3のデコードにはAdafruit_MP3を使用していますので先にインストールしておいてください。
本来はAdafruit製のARMチップ搭載ボード向けのライブラリなのですが、検証したところ特に変更を加えることなく動作しました。
また、MicroSDにはあらかじめ再生したいMP3ファイルを保存して本体に挿入しておいてください。

このサンプルソースでは下記3種類の出力方法をサポートしています。
使用したい出力先のコメントアウトを外して使ってください。 内蔵ブザー、Groveポートでの出力の場合は1ビットPCMのdigitalWrite出力とanalogWrite出力の2種類の出力方法があるのでお好みで。
個人的にはdigitalWriteが好きです。 まともな音質で鳴らしたければDACピンから信号を出力するのがベストだと思います。

接続例
Groveポート出力
DACピン出力

サンプルソース
#include <Seeed_FS.h>
#include <SD/Seeed_SD.h>

#include "Adafruit_MP3.h"
//set this to a value between 0 and 4095 to raise/lower volume
// DACピンから出力する場合
//#define VOLUME_MAX 4095

// 内蔵ブザーまたはGroveポートから出力する場合
#define VOLUME_MAX 512

const char *filename = "music.mp3";
File dataFile;
Adafruit_MP3 player;

void writeDacs(int16_t l, int16_t r){
  uint16_t vall = map(l, -32768, 32767, 0, VOLUME_MAX);
  uint16_t valr = map(r, -32768, 32767, 0, VOLUME_MAX);

  // 内蔵ブザーから鳴らす場合(analogWrite版)
  //analogWrite(WIO_BUZZER, vall);

  // 内蔵ブザーから鳴らす場合(digitalWrite版)
  if(vall > 256) {
    digitalWrite(WIO_BUZZER, HIGH);
  } else {
    digitalWrite(WIO_BUZZER, LOW);
  }
  
  // Groveポートから出力する場合(analogWrite版)
  //analogWrite(A0, vall);
  //analogWrite(A1, valr);
  
  // Groveポートから出力する場合(digitalWrite版)
  //if(vall > 256) {
  //  digitalWrite(D0, HIGH);
  //} else {
  //  digitalWrite(D0, LOW);
  //}
  //if(valr > 256) {
  //  digitalWrite(D1, HIGH);
  //} else {
  //  digitalWrite(D1, LOW);
  //}
  
  // DACピンから鳴らす場合
  //analogWrite(PIN_DAC0, vall);
  //analogWrite(PIN_DAC1, valr);
}

int getMoreData(uint8_t *writeHere, int thisManyBytes){
  int bytesRead = 0;
  int toRead = min(thisManyBytes, 768); //limit the number of bytes we can read at a time so the file isn't interrupted
  while(dataFile.available() && bytesRead < toRead){
    *writeHere = dataFile.read();
    writeHere++;
    bytesRead++;
  }
  return bytesRead;
}

void setup() {
  SD.begin(SDCARD_SS_PIN, SDCARD_SPI, 25000000);
  
  // 内蔵ブザーから出力する場合
  pinMode(WIO_BUZZER, OUTPUT);

  // Groveポートから出力する場合
  //pinMode(A0, OUTPUT);
  //pinMode(A1, OUTPUT);
  
  // DACピンから出力する場合
  //analogWriteResolution(12);
  //pinMode(PIN_DAC0, OUTPUT);
  //pinMode(PIN_DAC1, OUTPUT);
  
  dataFile = SD.open(filename);
  if(!dataFile){
    //Serial.println("could not open file!");
    while(1);
  }
  
  player.begin();
  
  //do this when there are samples ready
  player.setSampleReadyCallback(writeDacs);
  
  //do this when more data is required
  player.setBufferCallback(getMoreData);
  
  player.play();
}

void loop() {
  player.tick();
}


戻る