メロディICM8026S/M8058S収録曲リストと音声サンプル操作用のクラスライブラリ

収録曲一覧

  • IE含む古いブラウザでは正しく再生されない・曲名が表示されない場合があります
  • 区別のため、SEにはタイトルに🔊、楽曲には🎵の絵文字を付けています
  • 曲番号は送信コマンドで使用される数値と同じゼロ始まりの番号で付けてあります
  • M8026SとM8058Sには同一の楽曲がいくつか含まれています (音色や収録部分が若干異なっている場合もある)
  • 再生開始からLED端子への出力がなくなるまでを曲の長さとして計測しています
  • 楽曲のタイトルがわからないものがあり、空欄にしてあります
    • 曲名をご存知の方、教えてください。 掲示板に、「曲番号、曲名、M8026SまたはM8058Sのどちらの曲か」を書き込んでいただけると助かります。

M8026S 収録曲

M8026S 収録曲リスト
再生 曲番号 曲名 長さ [秒] 備考
再生 曲番号 曲名 長さ [秒] 備考

M8058S 収録曲

M8058S 収録曲リスト
再生 曲番号 曲名 長さ [秒] 備考
再生 曲番号 曲名 長さ [秒] 備考

クラスライブラリ

ヘッダファイルM80XXS.hinclude等のディレクトリに置き、#include "M80XXS.h"でインクルードしてください。 使い方はサンプルコードを参照してください。

サンプルコード

M80XXS.hのサンプルコード
#include <Arduino.h>
#include "M80XXS.h"

// M8058Sを使用する場合は以下のクラスを使ってください
auto melody = M8058S<12>(); // テンプレートの第一引数にM8058Sの'data'端子と接続されたGPIOピン番号を指定してください (この例ではGPIO#12を使用)

// M8026Sを使用する場合は以下のクラスを使ってください
auto melody = M8026S<12>(); // テンプレートの第一引数にM8026Sの'data'端子と接続されたGPIOピン番号を指定してください (この例ではGPIO#12を使用)

void setup() {
  Serial.begin(9600);

  // 初期化
  melody.begin();

  // 各種初期値を与えて初期化する場合は以下のオーバーロードを使用してください
  /*
  melody.begin(
    4,    // ボリューム初期値
    38,   // (省略可) 再生する曲の初期値
    true, // (省略可) LED出力を有効にするかどうか
    true  // (省略可) LED出力を有効にする場合、LEDを点滅させるかどうか
  );
  */
}

void loop() {
  // 曲番号3を再生する (0始まりの曲番号、M8026Sの場合: 0~25、 M8058Sの場合: 0~57)
  melody.play(3);

  // 以前のコマンドで再生された曲を再生する(リプレイ)
  melody.play();

  // 以前のコマンドで再生された曲の次の曲を再生する
  melody.playNext();

  // 以前のコマンドで再生された曲の前の曲を再生する
  melody.playPrev();

  // 再生を停止する
  melody.stop();

  // ボリュームを設定する
  melody.setVolume(4); // 0:最小 〜 7:最大
  melody.setVolumeMin(); // 最小ボリュームにする
  melody.setVolumeMax(); // 最大ボリュームにする
  melody.increaseVolume(); // ボリュームを1段階上げる
  melody.decreaseVolume(); // ボリュームを1段階下げる

  // 現在設定されているボリュームを取得する
  Serial.println(melody.getVolume());

  // ボリュームの最小値・最大値を取得する
  Serial.println(melody.minVolume()); // 0
  Serial.println(melody.maxVolume()); // 7

  // 収録されている曲数を取得する
  Serial.println(melody.numberOfMusics()); // M8026Sの場合: 26、 M8058Sの場合: 58
}

M80XXS.h

M8026S/M8058S操作用のクラスライブラリとなるヘッダファイルです。 ライセンスはMITライセンスです。

M80XXS.h
// 
// Copyright (c) 2020 smdn <smdn@smdn.jp>
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <Arduino.h>

#ifndef M80XXS_h
#define M80XXS_h

template <uint8_t pin_DATA, uint8_t NUM_OF_MUSICS>
class M80XXS;

template <uint8_t pin_DATA>
using M8058S = M80XXS<pin_DATA, 58>;

template <uint8_t pin_DATA>
using M8026S = M80XXS<pin_DATA, 26>;

template <uint8_t pin_DATA, uint8_t NUM_OF_MUSICS>
class M80XXS {
  private:
    enum Command : uint8_t {
      MUSICNUMBER_BASE      = 0x00,

      VOLUME_BASE           = 0xF0,

      MODE_SOUND_FLASHLED   = 0xE8,
      MODE_SOUND            = 0xE9,
      MODE_NOSOUND_FLASHLED = 0xEA,
      MODE_SOUND_LIGHTLED   = 0xEB,

      COMMAND_REPLAY        = 0xFB,
      COMMAND_FORWARD       = 0xFC,
      COMMAND_PREVIOUS      = 0xFD,
      COMMAND_VOLUME        = 0xFE,
      COMMAND_STOP          = 0xFF,
    };

  public:
    /*static*/ constexpr int numberOfMusics() { return NUM_OF_MUSICS; }
    /*static*/ constexpr int maxVolume() { return 7; }
    /*static*/ constexpr int minVolume() { return 0; }

    inline __attribute__ ((always_inline)) void begin() const
    {
      // set initial pin state
      pinMode(pin_DATA, OUTPUT);
      digitalWrite(pin_DATA, LOW);
    }

    void begin(
      const uint8_t& initialVolume,
      const uint8_t& initialMusicNumber = 0,
      const bool& enableLED = false,
      const bool& flashLED = false
    )
    {
      begin();

      // set initial volume
      sendCommand(MODE_NOSOUND_FLASHLED); setVolume(initialVolume);

      // set initial music
      sendCommand(MODE_NOSOUND_FLASHLED); play(initialMusicNumber);

      // set LED mode
      if (enableLED)
        sendCommand(flashLED ? MODE_SOUND_FLASHLED : MODE_SOUND_LIGHTLED);
      else
        sendCommand(MODE_SOUND);

      // then stop playing
      stop();
    }

    inline __attribute__ ((always_inline)) void setVolume(const uint8_t& newVolume)
    {
      sendCommand(VOLUME_BASE + (m_currentVolume = constrain(newVolume, minVolume(), maxVolume())));
    }

    inline __attribute__ ((always_inline)) void setVolumeMax() { setVolume(maxVolume()); }
    inline __attribute__ ((always_inline)) void setVolumeMin() { setVolume(minVolume()); }
    inline __attribute__ ((always_inline)) void increaseVolume() { setVolume(m_currentVolume == maxVolume() ? maxVolume() : m_currentVolume + 1); }
    inline __attribute__ ((always_inline)) void decreaseVolume() { setVolume(m_currentVolume == minVolume() ? minVolume() : m_currentVolume - 1); }
    inline __attribute__ ((always_inline)) const uint8_t& getVolume() { return m_currentVolume; }

    inline __attribute__ ((always_inline)) void play(const uint8_t& musicNumber) const
    {
      sendCommand(MUSICNUMBER_BASE + constrain(musicNumber, 0, NUM_OF_MUSICS));
    }

    inline __attribute__ ((always_inline)) void play()      const { sendCommand(COMMAND_REPLAY); }
    inline __attribute__ ((always_inline)) void playNext()  const { sendCommand(COMMAND_FORWARD); }
    inline __attribute__ ((always_inline)) void playPrev()  const { sendCommand(COMMAND_PREVIOUS); }
    inline __attribute__ ((always_inline)) void stop()      const { sendCommand(COMMAND_STOP); }

  private:
    uint8_t m_currentVolume;

    // command:
    //           6ms            2ms x 8bits
    //   H    _________________________________
    //        | HEADER |         COMMAND       |
    //        |        |b0|b1|b2|b3|b4|b5|b6|b7|
    //   L ___|        |__|__|__|__|__|__|__|__|___
    void sendCommand(const uint8_t& command) const
    {
      // header (6ms)
      digitalWrite(pin_DATA, HIGH);
      delayMicroseconds(6000);

      // command (2ms x 8bits)
      for (uint8_t mask = 0b1; mask; mask <<= 1) {
        // 0:  1.5ms   0.5ms
        //   H          ___
        //   L _________| |
        //
        // 1:  0.5ms   1.5ms
        //   H    _________
        //   L ___|       |
        uint8_t bit = command & mask;

        digitalWrite(pin_DATA, LOW);
        delayMicroseconds(bit ? 500 : 1500);

        digitalWrite(pin_DATA, HIGH);
        delayMicroseconds(bit ? 1500 : 500);
      }

      digitalWrite(pin_DATA, LOW);

      // interval to next command
      delayMicroseconds(200);
    }
};

#endif // M80XXS_h

配線例

M8026Sの配線例
GND DATA VDD M8026S 104 100nF 475 4.7µF 100Ω 8Ω 0.5W
M8058Sの配線例
DATA GND VDD M8058S 475 4.7µF 8Ω 0.5W R2 100Ω
  • 図中のLEDは必要なければ省略可能です
  • 図中ではM8026S/M8058SをDIPとして作図していますが、実物はSOPです

既知の不具合・問題点

  • M8026S/M8058Sは、任意のコマンドを受信するたびに自動的に再生を開始する動作となっているため、以下の問題点があります。
    • 初期値を与えてbegin()メソッドを呼び出すと、短時間のノイズが再生されます。 このノイズを避けたい場合は、引数なしでbegin()メソッドを呼び出してください。
    • M8058Sでは、setVolume()等のメソッドでボリュームを設定すると、自動的に再生されます。 ボリューム設定後に再生させたくない場合は、ボリューム設定直後にstop()メソッドを呼び出す、あるいは再生直前まで音量を設定しないなどの方法を採ってください。

動作状況

以下の環境・ボードでの動作を確認しています。

動作確認済みボード

  • Arduino Nano ATmega328 (New Bootloader)
  • ESP32-DevKitC ESP-WROOM-32開発ボード (秋月電子通商 ESP32-DevKitC (M-11819))

IDE

  • Ubuntu 20.04 + PlatformIO IDE 1.10.0
  • Ubuntu 20.04 + Arduino IDE 1.8.10

変更履歴

2020-06-19

初版

  • 再生・停止・音量設定・LED設定の各種全コマンドをサポート