前回、
別々で音を出すならステレオ出力っぽいことも出来ますね
と書いたので、ステレオ出力もやりました。
曲は例によって魔界塔士SaGaのタイトル画面の曲です。
波形を見てみると、絵に描いたようなキレイな矩形波が出ています。
ライブラリは3つ。A tiny MML parser、Metro Library、Arduino 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自体は音源用途なんて全然考えてないでしょうから、ボリューム下げたりとかこれ以上音数増やしたりとか音色変えたりとか、そういう拡張性は無いですけどね。