NEUTRINOの歌詞入力を簡単にしてみた②

本記事では、NEUTRINOの歌詞入力を少し簡単にするツールの処理内容を紹介していきます。

どんなツールっすか? という方は、前回記事をお読みくだされ。
(プライベート開発用のgitアカウント作るのが億劫で更新が遅くなってしまった...)

chord-in-code.hatenablog.com


今回のお品書き

Pythonコード

実際に使用しているコードは以下です。

import os
import glob
from pykakasi import kakasi

def conv4MuseScore(text_file):
    """
    テキストファイルの中身をMuseScoreに貼り付けられる形に変換する。\n
    Args:
        text_file : 読み込む歌詞ファイル(.txt)
    Returns:
        convert_file : 変換後の歌詞ファイル(.txt)
    """
    # 変換クラスの生成
    kaka = kakasi()

    # テキストファイル読み込み
    with open(text_file, "r", encoding="utf-8") as f:
        lyrics = [s.strip() for s in f.readlines()] # 改行ごとにリスト化(1)
        lyrics = [i for i in lyrics if i != ""] # 空欄を削除(2)
    
    # 全単語を統合する文字列
    all_str = ""
    
    # 1行ごとに変換
    for lyric in lyrics:
        lyric = lyric.replace(" ", "").replace(" ", "") # 半角&全角スペースを削除(3)
        sentence = kaka.convert(lyric) # ひらがな変換(4)

        for word in sentence:
            all_str += word["hira"] # 1単語ずつ統合(5)
    
    # MuseScore用の文字列
    ms_str = ""

    # 半角スペースの挿入(6)
    for char in list(all_str):
        if char in ["ゃ", "ゅ", "ょ"]:
            ms_str += char
        else:
            ms_str += " " + char
    
    # 最初の半角スペースを削除(7)
    ms_str = ms_str[1:]

    # ファイル名取得
    file_name = os.path.splitext(os.path.basename(text_file))[0]

    # 変換ファイルに書き込み
    with open("./02_converted_data/" + file_name + "_converted.txt", "w", encoding="utf-8") as f:
        f.write(ms_str)
    
    return "./02_converted_data/" + file_name + "_converted.txt"

def main():
    text_list = glob.glob("./01_text_data/*.txt")

    for tl in text_list:
        conv4MuseScore(tl)
    
    return 0

if __name__ == '__main__':
    print("--main start--")

    main()

    print("--main end--")

本記事では上記コード内にコメントを入れてある(1)~(7)の処理内容を説明します。
(globやらファイル出力やらは本題じゃないので説明しません)

処理内容

ここからは処理内容について説明していきます。
上述のコードはざっと以下の様な処理手順になっています。

  1. テキストファイル読み込み
  2. テキストを行単位のリストに変換
  3. リストを一繋ぎのひらがなに変換
  4. MuseScore用に変換
  5. ファイルへの出力

1&5については、ありふれた処理なので特に触れませんが、
2~4はそれぞれ何をしているのか記載しておきます。

なお、分かりやすくするために、ここからは以下の様な
テキストファイルの変換を例にして説明していきます。

明日の天気は

晴れ 時々 曇り

でしょう

テキストを行単位のリストに変換

テキストファイルを読み込んで、行単位のリストを作成します。

text_file = "test_message.txt" # テキストファイルを指定

with open(text_file, "r", encoding="utf-8") as f:
    lyrics = [s.strip() for s in f.readlines()] # 改行ごとにリスト化
    print(lyrics)

# => ['明日の天気は', '', '晴れ\u3000時々 曇り', '', 'でしょう']

「\u3000」はUnicodeエスケープシーケンスでの全角スペースのことです。

見た目的にとても気になりますが、
一旦無視してリスト内の空の要素を取り除きます。

lyrics = [i for i in lyrics if i != ""] # 空欄を削除
print(lyrics)

# => ['明日の天気は', '晴れ\u3000時々 曇り', 'でしょう']

これで、必要な行をリストとして取得することができました。

リストを一繋ぎのひらがなに変換

ここでは先ほど取得したリストに対してforループを回して
1行毎にひらがなに変換していきます。

ひらがなへの変換はpykakasiというライブラリを使ってみました。
pykakasiの詳細な使い方は以下のサイトを見てくだされ。
office54.net

pykakasiを使うと1つの文を単語に分解してから
ひらがなに変換してくれます。

以下の様なイメージ。

お仕事って大変だよね
⇒['お', '仕事', 'って', '大変', 'だよね']
⇒['お', 'しごと', 'って', 'たいへん', 'だよね']

(あくまでイメージです。本当はひらがな以外も含んだ辞書型データのリストが取得されます。)

ということで、pykakasiを使って1行毎に変換していくわけなのですが、
この処理をする時に余計なスペースが入っていると変換が失敗しやすくなります。

明日
⇒ちゃんと「あした」と変換される

明 日
⇒1単語と認識されず、「めい」「にち」と変換される

なので、pykakasiに渡す前にスペースは全て削除しておきます。

# 1行ごとに変換
for lyric in lyrics:
    lyric = lyric.replace(" ", "").replace(" ", "") # 半角&全角スペースを削除
    print(lyric)

# (以下、出力結果)
# 明日の天気は
# 晴れ時々曇り
# でしょう

無事に不要なスペースを削除できたので、pykakasiを使ってひらがな情報を取得します。

from pykakasi import kakasi
kaka = kakasi()

# (中略)

# 1行ごとに変換
for lyric in lyrics:
    lyric = lyric.replace(" ", "").replace(" ", "") # 半角&全角スペースを削除
    sentence = kaka.convert(lyric) # ひらがな変換

    # 単語ごとにループ処理
    for word in sentence:
        print(word["hira"])

# (以下、出力結果)
# あした
# の
# てんき
# は
# はれ
# ときどき
# くもり
# でしょう

あとは、各単語を足し合わせれば一繋ぎのひらがなは作成できますね。

足し合わせる処理の説明は、for文で一つ一つ足していくだけなので
ここでの説明は割愛します。

MuseScore用に変換

ここまでで「漢字、改行、スペースを含むテキスト」を
「一行のひらがな」に変換するところまではできました。

あとはNEUTRINO用に文字の間に半角スペースを入れていきます。

all_str = "あしたのてんきははれときどきくもりでしょう"

# MuseScore用の文字列
ms_str = ""

# 半角スペースの挿入
for char in list(all_str):
    ms_str += " " + char

print(ms_str)

# =>  あ し た の て ん き は は れ と き ど き く も り で し ょ う

list(文字列)で一文字ずつのリストを作成できることさえ知っていれば
for文で半角スペースを挟むだけなので、特に難しくないと思います。

ただし、このままでは文末の「でしょう」が「で し ょ う」の4音扱いになってしまいます。
「ゃ」、「ゅ」、「ょ」を発音する時は直前の文字と合わせて1音扱いが適切なので
「ゃ」、「ゅ」、「ょ」の前には半角スペースを入れないようにします。

all_str = "あしたのてんきははれときどきくもりでしょう"

# MuseScore用の文字列
ms_str = ""

# 半角スペースの挿入
for char in list(all_str):
    if char in ["ゃ", "ゅ", "ょ"]:
        ms_str += char
    else:
        ms_str += " " + char

print(ms_str)

# =>  あ し た の て ん き は は れ と き ど き く も り で しょ う

これで1音毎に間に半角スペースを入れることができました。
あとは、先頭に余計なスペースが残っているので消しておきます。

ms_str = " あ し た の て ん き は は れ と き ど き く も り で しょ う"

# 最初の半角スペースを削除
ms_str = ms_str[1:]

print(ms_str)

# => あ し た の て ん き は は れ と き ど き く も り で しょ う

コード配布

前回のexeは特に配布していませんが、Pythonコードはgithubで公開しておきます。
GitHub - tory0601/lyrics4MuseScore


なお、使用しているpykakasiがGNU General Public License v3 or later (GPLv3+)に指定されているので
このコードもGNU General Public License v3 or later (GPLv3+)とします。


ではでは、今回はこの辺で。