文章からドラムパターンを生成する
はじめに
こんばんは。書肆書斎店主です。
最近、毎日当店で販売している本を引用とともに紹介する投稿をInstagramとtwitterで続けています。
画像の上にタイプライター風に文字が出てきます。
フリー音源でキーボードの音も重ねています。
それで何を思ったかというと
店主はバンドをやっていまして、ドラムを叩くんですね。
なので、どうせならドラムと絡めたいなと思いまして。(ドラムが好きだから)
最近こんなんあるじゃないですか、それをドラムでやったらいいんじゃないかと。
なぜ叩かない?
いや、叩いてもいいんですけど、スタジオいかなきゃいけないし、結構練習とか必要なので、大変そうで実現可能性は低いなーと思ってたんですけど、とりあえず、どんな感じになるかだけやってみるか^^っていうのがこの記事のゴールです。
結論、特に素敵ではないので使いませんが、タイトルの通りの実装はできたので公表します。
実装方法
★実装までの過程
ChatGPTに書かせました
pythonでmidiが出力できます
引用文を形態素分析して、母音と子音にドラムの楽器をマッピングします
実装内容
.pyの中身を抜粋します。ほぼコピペでいけます。
import ライブラリ
import os
from midiutil import MIDIFile
import romkan # romkanを使ってひらがなをローマ字に変換
import fugashi # 形態素解析器
import jaconv # ひらがな変換用
音素↔ドラムマッピング
# 文字に対応するドラム音のマッピング(全て異なる楽器にする)
drum_mapping_consonant = {
"k": 36, # バスドラム
"s": 38, # スネアドラム
"t": 41, # フロアタム
"n": 43, # ハイトム
"h": 45, # ロータム
"m": 47, # ロータム
"r": 48, # ミディアムタム
"w": 49, # クラッシュシンバル
"y": 51 # ライドシンバル
}
drum_mapping_vowel = {
"a": 42, # ハイハット クローズ
"i": 44, # ハイハット オープン
"u": 46, # タム
"e": 50, # ライドベル
"o": 52 # チャイナシンバル
}
肝になる処理
ファイル名を引用文から取得するとか、重複してたらカウントアップとか気の利いた処理も入れている(全然本筋じゃない。本筋はGPTくんが勝手に書いてくれたからノシ)
# 漢字交じりのテキストをひらがなに変換する関数
def text_to_hiragana(text):
# GenericTaggerを使用してfugashiのTaggerを初期化
tagger = fugashi.GenericTagger('-r hogehoge -d hogehoge') #mecablibのdirとかを指定する。fugashiの仕様
words = tagger(text) # テキストを形態素解析
hiragana_text = ""
for word in words:
# feature[7]が読み仮名(かな)を含む
if len(word.feature) > 7 and word.feature[7]:
kana = word.feature[7] # ひらがなを取得
hiragana_text += jaconv.kata2hira(kana) # カタカナをひらがなに変換
else:
hiragana_text += word.surface # 読み仮名がない場合はそのまま
return hiragana_text
# 子音と母音を同時に発音させる関数
def add_drum_notes(midi, track, time, consonant, vowel):
# 子音のドラムを追加
if consonant in drum_mapping_consonant:
midi.addNote(track, 9, drum_mapping_consonant[consonant], time, 1, 100)
# 母音のドラムを追加
if vowel in drum_mapping_vowel:
midi.addNote(track, 9, drum_mapping_vowel[vowel], time, 1, 100)
# 重複しないファイル名を生成する関数
def generate_unique_filename(base_name, directory):
count = 1
file_name = f"{base_name}.mid"
file_path = os.path.join(directory, file_name)
# ファイルがすでに存在する場合、カウントアップして連番を付ける
while os.path.exists(file_path):
file_name = f"{base_name}_{count}.mid"
file_path = os.path.join(directory, file_name)
count += 1
return file_path
# ひらがなをローマ字に変換し、対応するドラム音を再生する関数
def text_to_drums(text, directory="."):
# Create a MIDI object
midi = MIDIFile(1)
track = 0
time = 0
midi.addTrackName(track, time, "Text to Drum Beat")
midi.addTempo(track, time, 500) # テンポ500
# テキストをひらがなに変換
hiragana_text = text_to_hiragana(text)
# ひらがなをローマ字に変換
romaji_text = romkan.to_roma(hiragana_text)
# テキストの最初の5文字をファイル名に使用
base_file_name = romaji_text[:5] if len(romaji_text) >= 5 else romaji_text
# 重複しないファイル名を生成
file_path = generate_unique_filename(base_file_name, directory)
# ローマ字テキストを一文字ずつ解析
i = 0
while i < len(romaji_text):
consonant = None
vowel = None
# もし子音があれば、その次に母音を確認
if romaji_text[i] in drum_mapping_consonant:
consonant = romaji_text[i]
if i + 1 < len(romaji_text) and romaji_text[i + 1] in drum_mapping_vowel:
vowel = romaji_text[i + 1]
i += 1 # 母音まで処理したので1つ追加でスキップ
elif romaji_text[i] in drum_mapping_vowel:
vowel = romaji_text[i]
# 子音と母音を同時に再生
add_drum_notes(midi, track, time, consonant, vowel)
time += 1 # 次のタイミングへ
i += 1 # 次の文字へ
# MIDIファイルに書き出し
with open(file_path, "wb") as output_file:
midi.writeFile(output_file)
print(f"MIDIファイルが生成されました: {file_path}")
引用文入力と呼び出し
# 任意の日本語テキスト(漢字交じりでもOK)
text = "「もっと辺鄙な村に行きたい」とだだっ子のように訴えた結果、私たちはロイ・ティヤとは反対側、つまり西側の村を回ることになった。"
# ドラムパターンを生成
text_to_drums(text)
サンプル
上記の通りで実行すると
"「mott.mid"というファイルが出力されるので、ガレバンとかに取り込む。
とりあえずできると↓みたいな感じ。
結論
ドラマー的には割と満足したけど、特に素敵ではないので不採用。