はじめに
近頃、楽曲生成に興味が湧いてきたため、第一歩としてMagentaを使用したドラム生成で遊んでみようと思います。
Demo
こちらは、デモにあったコードを修正して試しに作ってみたデモになります。
区切り線より左側は、Userが入力し、それを元にMusicRNNのdrum_kitモデルを使用して続きを作成します。
Magentaとは?
An open source research project exploring the role of machine learning as a tool in the creative process.
Googleが出している、音楽などの機械学習プロジェクトのようです。
動かして見たかったので調べたところ、jsのライブラリがあり、web上で簡単に動かせそうだったので今回はこれを使ってみます。
RNNによる生成部分
let rnn = new mm.MusicRNN(
"https://storage.googleapis.com/download.magenta.tensorflow.org/tfjs_checkpoints/music_rnn/drum_kit_rnn"
);
まず、MusicRNNでどのモデルを使うか指定します。今回はdrum_kit_rnn
というドラムのモデルを使います。
/** パターンを生成 */
function generatePattern(seed, length) {
// シードをnoteSequenceに変換
let seedSeq = toNoteSequence(seed);
// RNNモデルを使ってシードから新しいシーケンスを生成
return rnn
.continueSequence(seedSeq, length, temperature)
.then((r) => seed.concat(fromNoteSequence(r, length)));
}
こちらが、実際にユーザーの入力したシード(Demoの赤い部分)から続きを作成する実装になります。
rnn.continueSequence
はsequenceからその続きを生成してくれそうです。
そのsequenceを入れるために、ユーザーからの入力であるseedをsequenceに変換する必要ありそうです。toNoteSequence()
は以下のようになっており、mm.sequences.quantizeNoteSequence()
を使用しています。
function toNoteSequence(pattern) {
// パターンをノートシーケンスに変換
return mm.sequences.quantizeNoteSequence(
{
// 1クォーターあたりのティック数を設定
ticksPerQuarter: 220,
// パターンの全体時間を設定(パターンの長さを2で割る)
totalTime: pattern.length / 2,
// 拍子記号を設定(4/4拍子)
timeSignatures: [
{
time: 0,
numerator: 4,
denominator: 4,
},
],
// テンポを設定(120 BPM)
tempos: [
{
time: 0,
qpm: 120,
},
],
// パターンの各ステップをノートに変換
notes: _.flatMap(pattern, (step, index) =>
step.map((d) => ({
// ドラムのMIDIピッチを設定
pitch: midiDrums[d],
// ノートの開始時間を設定
startTime: index * 0.5,
// ノートの終了時間を設定
endTime: (index + 1) * 0.5,
}))
),
},
// 精度を設定?
1
);
}
そもそもNoteSequenceとは?
チュートリアルには以下のように記載がありました。
Everything in @magenta/music is centered around NoteSequences. This is an abstract representation of a series of notes, each with different pitches, instruments and strike velocities, much like MIDI.
引用:https://hello-magenta.glitch.me/
MIDIのような形式であり、音符の音程、楽器、打鍵速度などを表現しているようです。
サンプルとして以下のような形式になっています。
DRUMS = {
notes: [
{ pitch: 36, quantizedStartStep: 0, quantizedEndStep: 1, isDrum: true },
{ pitch: 38, quantizedStartStep: 0, quantizedEndStep: 1, isDrum: true },
{ pitch: 42, quantizedStartStep: 0, quantizedEndStep: 1, isDrum: true },
{ pitch: 46, quantizedStartStep: 0, quantizedEndStep: 1, isDrum: true },
{ pitch: 42, quantizedStartStep: 2, quantizedEndStep: 3, isDrum: true },
{ pitch: 42, quantizedStartStep: 3, quantizedEndStep: 4, isDrum: true },
{ pitch: 42, quantizedStartStep: 4, quantizedEndStep: 5, isDrum: true },
{ pitch: 50, quantizedStartStep: 4, quantizedEndStep: 5, isDrum: true },
{ pitch: 36, quantizedStartStep: 6, quantizedEndStep: 7, isDrum: true },
{ pitch: 38, quantizedStartStep: 6, quantizedEndStep: 7, isDrum: true },
{ pitch: 42, quantizedStartStep: 6, quantizedEndStep: 7, isDrum: true },
{ pitch: 45, quantizedStartStep: 6, quantizedEndStep: 7, isDrum: true },
{ pitch: 36, quantizedStartStep: 8, quantizedEndStep: 9, isDrum: true },
{ pitch: 42, quantizedStartStep: 8, quantizedEndStep: 9, isDrum: true },
{ pitch: 46, quantizedStartStep: 8, quantizedEndStep: 9, isDrum: true },
{ pitch: 42, quantizedStartStep: 10, quantizedEndStep: 11, isDrum: true },
{ pitch: 48, quantizedStartStep: 10, quantizedEndStep: 11, isDrum: true },
{ pitch: 50, quantizedStartStep: 10, quantizedEndStep: 11, isDrum: true },
],
quantizationInfo: {stepsPerQuarter: 4},
tempos: [{time: 0, qpm: 120}],
totalQuantizedSteps: 11
};
その他のモデル
今回はRNNというモデルを使用しましたが、他にも種類があるみたいです。
@magenta/music has several Machine Learning models, each with different strengths:
- MusicRNN - you give it a NoteSequence, and it continues it in the style of your original NoteSequence.
- MusicVAE - generates brand new NoteSequences or interpolates between two sequences.
- Onsets and Frames -- transcribes piano audio
引用:https://hello-magenta.glitch.me/
その他できること
様々なDemoがあり、これを見てる感じ、他にもいろいろなことができそうです。
年末の暇つぶしネタとしてもっと触ってみるのも面白そうです。
関連する面白そうな記事
参考