文章からドラムパターンを生成する

はじめに

こんばんは。書肆書斎店主です。
最近、毎日当店で販売している本を引用とともに紹介する投稿を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"というファイルが出力されるので、ガレバンとかに取り込む。

とりあえずできると↓みたいな感じ。

「もっと辺鄙な村に行きたい」とだだっ子のように訴えた結果、私たちはロイ・ティヤとは反対側、つまり西側の村を回ることになった。

アヘン王国潜入記 P.82

結論

ドラマー的には割と満足したけど、特に素敵ではないので不採用。

いいなと思ったら応援しよう!