LoginSignup
0
0

More than 1 year has passed since last update.

Magenta.js の MusicRNN の basic_rnn/melody_rnn/chord_pitches_improv を試す(環境は p5.js Web Editor上)

Last updated at Posted at 2021-11-23

以下の記事に書いた 「Magenta」の JavaScript 版である Magenta.js のお試しの話の続きです。

●機械学習・AI で音を作れる「Magenta」の JavaScript 版(Magenta.js)を p5.js Web Editor上で動かしてみる - Qiita
 https://qiita.com/youtoy/items/32eedd5c5c9280fe3f0f

今回は、上記の記事でも試した「MusicRNN」の話です。
ちなみに MusicRNN は、「利用者が特定のメロディを入力すると、その続きを作ってくれる」という機械学習モデルになっているようです。

上記の記事の中では、公式の手順を試す中で MusicRNN の「basic_rnn」を使う部分がありました。
それ以外に、「melody_rnn」や「chord_pitches_improv」といったものもあるようだったので、今回はそれらを試すプログラムを作っていきます。
MusicRNNで試すもの.jpg

なお、上記の画像の中で「drum_kit_rnn」というのがありますが、これは別の機会に試していければと思います。

【追記】 音が鳴る様子の動画を追加しました

どんな音が作られるのか、この記事で書いていたプログラムを実行しているところを、キャプチャしたものをツイートしました。

音を作る

p5.js Web Editor の下準備

前回の記事の手順と同じように、まずは p5.js Web Editor の index.html でライブラリを読み込みます(前回と同じ、以下を読み込み)。

<script src="https://cdn.jsdelivr.net/npm/@magenta/music@^1.0.0"></script>

次に、sketch.js を作っていきます。

JavaScript のプログラム

今回、入力として与えるデータを 2つ増やしてみました(「チューリップ」と「かえるの歌」を用意してみました)。
また preload() の部分で「basic_rnn/melody_rnn/chord_pitches_improv」の 3つをそれぞれ読み込んでいます。

本来は、もう少しきれいに書けそうな内容になってますが、とりあえず版ということで...

const TWINKLE_TWINKLE = {
  notes: [
    { pitch: 60, startTime: 0.0, endTime: 0.5 },
    { pitch: 60, startTime: 0.5, endTime: 1.0 },
    { pitch: 67, startTime: 1.0, endTime: 1.5 },
    { pitch: 67, startTime: 1.5, endTime: 2.0 },
    { pitch: 69, startTime: 2.0, endTime: 2.5 },
    { pitch: 69, startTime: 2.5, endTime: 3.0 },
    { pitch: 67, startTime: 3.0, endTime: 4.0 },
    { pitch: 65, startTime: 4.0, endTime: 4.5 },
    { pitch: 65, startTime: 4.5, endTime: 5.0 },
    { pitch: 64, startTime: 5.0, endTime: 5.5 },
    { pitch: 64, startTime: 5.5, endTime: 6.0 },
    { pitch: 62, startTime: 6.0, endTime: 6.5 },
    { pitch: 62, startTime: 6.5, endTime: 7.0 },
    { pitch: 60, startTime: 7.0, endTime: 8.0 },
  ],
  totalTime: 8,
};

const TULIP = {
  notes: [
    { pitch: 60, startTime: 0.0, endTime: 0.5 },
    { pitch: 62, startTime: 0.5, endTime: 1.0 },
    { pitch: 64, startTime: 1.0, endTime: 2.0 },
    { pitch: 60, startTime: 2.0, endTime: 2.5 },
    { pitch: 62, startTime: 2.5, endTime: 3.0 },
    { pitch: 64, startTime: 3.0, endTime: 4.0 },
    { pitch: 67, startTime: 4.0, endTime: 4.5 },
    { pitch: 64, startTime: 4.5, endTime: 5.0 },
    { pitch: 62, startTime: 5.0, endTime: 5.5 },
    { pitch: 60, startTime: 5.5, endTime: 6.0 },
    { pitch: 62, startTime: 6.0, endTime: 6.5 },
    { pitch: 64, startTime: 6.5, endTime: 7.0 },
    { pitch: 62, startTime: 7.0, endTime: 7.5 },
  ],
  totalTime: 7.5,
};

const FROG = {
  notes: [
    { pitch: 60, startTime: 0.0, endTime: 0.5 },
    { pitch: 62, startTime: 0.5, endTime: 1.0 },
    { pitch: 64, startTime: 1.0, endTime: 1.5 },
    { pitch: 65, startTime: 1.5, endTime: 2.0 },
    { pitch: 64, startTime: 2.0, endTime: 2.5 },
    { pitch: 62, startTime: 2.5, endTime: 3.0 },
    { pitch: 60, startTime: 3.0, endTime: 4.0 },
  ],
  totalTime: 4,
};

let player;

function preload() {
  music_rnn_melody_rnn = new mm.MusicRNN(
    "https://storage.googleapis.com/magentadata/js/checkpoints/music_rnn/melody_rnn"
  );
  music_rnn_melody_rnn.initialize();

  music_rnn_chord_pitches_improv = new mm.MusicRNN(
    "https://storage.googleapis.com/magentadata/js/checkpoints/music_rnn/chord_pitches_improv"
  );
  music_rnn_chord_pitches_improv.initialize();

  music_rnn_basic_rnn = new mm.MusicRNN(
    "https://storage.googleapis.com/magentadata/js/checkpoints/music_rnn/basic_rnn"
  );
  music_rnn_basic_rnn.initialize();
}

function setup() {
  createCanvas(400, 400);
  background(220);

  player = new mm.Player();
}

function draw() {}

function keyPressed() {
  if (!player.isPlaying()) {
    let rnn_steps, rnn_temperature;

    switch (key) {
      case "q":
        player.start(TWINKLE_TWINKLE);
        break;
      case "w":
        makeMusicBasic(TWINKLE_TWINKLE, 4, 16 * 2, 1.5);
        break;
      case "e":
        makeMusicBasic(TWINKLE_TWINKLE, 4, 16 * 8, 1.5);
        break;
      case "r":
        makeMusicMelody(TWINKLE_TWINKLE, 4, 16 * 2, 1.5);
        break;
      case "t":
        makeMusicChord(TWINKLE_TWINKLE, 4, 16 * 2, 1.5, ["G", "Em", "C", "D"]);
        break;

      case "a":
        player.start(TULIP);
        break;
      case "s":
        makeMusicBasic(TULIP, 4, 16 * 2, 1.5);
        break;

      case "z":
        player.start(FROG);
        break;
      case "x":
        makeMusicBasic(FROG, 4, 16 * 2, 1.5);
        break;
    }
  } else if (player.isPlaying()) {
    switch (key) {
      case " ":
        console.log("Stop");
        player.stop();
        break;
    }
  }
}

function makeMusicBasic(SONG, steps_per_quarter, rnn_steps, rnn_temperature) {
  const qns = mm.sequences.quantizeNoteSequence(SONG, steps_per_quarter);
  music_rnn_basic_rnn
    .continueSequence(qns, rnn_steps, rnn_temperature)
    .then((sample) => player.start(sample));
}

function makeMusicMelody(SONG, steps_per_quarter, rnn_steps, rnn_temperature) {
  const qns = mm.sequences.quantizeNoteSequence(SONG, steps_per_quarter);
  music_rnn_melody_rnn
    .continueSequence(qns, rnn_steps, rnn_temperature)
    .then((sample) => player.start(sample));
}

function makeMusicChord(
  SONG,
  steps_per_quarter,
  rnn_steps,
  rnn_temperature,
  chord_progression
) {
  const qns = mm.sequences.quantizeNoteSequence(SONG, steps_per_quarter);
  music_rnn_chord_pitches_improv
    .continueSequence(qns, rnn_steps, rnn_temperature, chord_progression)
    .then((sample) => {
      console.log(sample);
      player.start(sample);
    });
}

上記を実行して、あとは特定のキーを押下していけば、以下の内容を試せます。

  • 入力をそのまま実行
    • きらきら星、チューリップ、かえるの歌 の3つ
  • 音を生成1: basic_rnn
    • 3つの入力のそれぞれを、32ステップで指定(他のパラメータは前回の記事と同様)
    • きらきら星について、128ステップで指定(他のパラメータは前回の記事と同様)
  • 音を生成2・3: melody_rnn/chord_pitches_improv
    • きらきら星について、32ステップで指定(他のパラメータは前回の記事と同様)

上記を試してみると、それぞれで異なる音が鳴るのが確認できました。

補足: chord_pitches_improv を使った場合

chord_pitches_improv を使った場合だけ、 continueSequence() でのパラメータ指定が他と異なります。

公式情報の continueSequence の部分で、以下の画像中に出てきている「chordProgression」の指定をしています。
continueSequenceのchordProgression.jpg

これは、basic_rnn や melody_rnn を使った場合と同じ処理内容を、chord_pitches_improv を使った場合にも用いてみたところ、エラーメッセージで chordProgression に関するメッセージが出たためです。
今回のプログラム中では、公式情報の例に記載されている「["G", "Em", "C", "D"]」を指定してみました。

余談

上記の補足の話の中に出てくる「tonalパッケージ」というのも気になりました。

●tonaljs/tonal: A functional music theory library for Javascript
 https://github.com/tonaljs/tonal

ドキュメントをざっくり見てみたところ、音系の処理を扱うのに便利そうでした。
tonaljsのドキュメント.jpg

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0