Arduino本体のみでMMLをステレオ再生

前回

別々で音を出すならステレオ出力っぽいことも出来ますね

と書いたので、ステレオ出力もやりました。
曲は例によって魔界塔士SaGaのタイトル画面の曲です。

波形を見てみると、絵に描いたようなキレイな矩形波が出ています。
square_wave

ライブラリは3つ。A tiny MML parserMetro LibraryArduino Tone Libraryが必要です。
D8,D9からスピーカー2個につなげてるだけなので、さすがに回路図は省略。
スケッチはこんな。


#include <Metro.h>
#include <Tone.h>
#include <mml.h>

const word noteFreq[] = {
  0,  9,  9, 10,  10, 11,   12,	12,	13,	14,	15,	15,
  16,  17, 18, 19,  21, 22,  23,	25,	26,	28,	29,	31,
  33,  35, 37,	39,  41, 44,  46,	49,	52,	55,	58,	62,
  65,	69, 73,	78,  82, 87,  93,	98,	104,	110,	117,	124,
  131, 139, 147, 156, 165, 175, 185,	196,	208,	220,	233,	247,
  262, 277, 294, 311, 330, 349, 370,	392,	415,	440,	466,	494,
  523, 554, 587, 622, 659, 699, 740,	784,	831,	880,	932,	988,
  1047, 1109, 1175, 1245, 1319, 1397,	1480,	1568,	1661,	1760,	1865,	1976,
  2093, 2218, 2349, 2489, 2637,	2794,	2960,	3136,	3322,	3520,	3729,	3951,
  4186, 4435, 4699, 4978, 5274,	5587,	5920,	6272,	6645,	7040,	7459,	7902,
  8372, 8870, 9397, 9956, 10548,11175,	11840,	12544
};

// Tone define
const byte CH_COUNT = 2;
Tone tones[CH_COUNT];

// Pin define
const byte SND_PIN[CH_COUNT] = {8,9};

// mml define
MML mml[CH_COUNT];
MML_OPTION mmlopt;
char *text[CH_COUNT] = {
  "o5 l16 e8e8b2 b-b>d-8<b1 >e8e8b2b-b>d-8<b1",
  "o6 l16 b1< e8e8b2b-b>d-8<b1 >e8e8b2b-b>d-8"
};

// Metro Timer
Metro toneMetro[CH_COUNT] = {Metro(), Metro()};

static byte ch[CH_COUNT] = {0,1};
static void mml_callback(MML_INFO *p, void *extobj)
{
  byte* t_no = (byte*)extobj;
  switch (p->type) {
    case MML_TYPE_NOTE:
      {
      MML_ARGS_NOTE *args = &(p->args.note);
      snd(args->number, args->ticks, *t_no);
      }
      break;
    case MML_TYPE_REST:
      {
      MML_ARGS_REST *args = &(p->args.rest);
      snd(0, args->ticks, *t_no);
      }
      break;
    default:
      snd(0,0,*t_no);
      break;
  }
}

void snd(int num, int ms, byte tone_no)
{
  if (num == 0){
    tones[tone_no].stop();
  }else{
    tones[tone_no].play(noteFreq[num]);
  }
  toneMetro[tone_no].interval(ms);
}

void setup()
{
  MML_OPTION_INITIALIZER(&mmlopt, 5, 8, 600);
  for (int i = 0; i < CH_COUNT; i++){
    pinMode(SND_PIN[i], OUTPUT);
    tones[i].begin(SND_PIN[i]);
    mml_init(&mml[i], mml_callback, &ch[i]);
    snd(0,0,i);
    mml_setup(&mml[i], &mmlopt, text[i]);
  }
}
void loop()
{
  for (int i = 0; i < CH_COUNT; i++){
    if (toneMetro[i].check() == 1){
      if(mml_fetch(&mml[i]) != MML_RESULT_OK){
        snd(0, 0, i);
        mml_setup(&mml[i], &mmlopt, text[i]);
      }
    }
  }
}

やってる事はYMZ294でステレオ出力やってた時と大して変わらないんですが、抵抗とスピーカー2個用意するだけで鳴らせるのが良いかなと。
Arduino自体は音源用途なんて全然考えてないでしょうから、ボリューム下げたりとかこれ以上音数増やしたりとか音色変えたりとか、そういう拡張性は無いですけどね。


コメントを残す