PythonでCSA形式の棋譜データを読み込む

pythonで棋譜データを扱う

棋譜データをpythonで読み込む方法についてのメモです。こちらのライブラリを使用させて頂いています。
GitHub - gunyarakun/python-shogi: A pure Python shogi library with move generation and validation and handling of common formats.

元となる棋譜データはCSA形式を想定しています。サンプルデータには「将棋DB2」のCSA形式ファイルを使用しました。
羽生善治 vs. 藤井猛 順位戦 - 無料の棋譜サービス 将棋DB2

サンプルコード

import shogi.CSA

kif = shogi.CSA.Parser.parse_file('test.csa')[0]

board = shogi.Board()
for move in kif['moves']:
    # どこからどこに移動したか USIプロトコル形式
    print(move)
    # 移動
    board.push_usi(move)

    # 盤面表示
    print(board) # テキスト形式(ASCII文字)
    print(board.kif_str()) # テキスト形式(KIFスタイル)

    # 占有している駒の位置 右下から左に移動という方向で表記されている
    print('{:0=81b}'.format(board.occupied[shogi.BLACK]))# 先手
    print('{:0=81b}'.format(board.occupied[shogi.WHITE]))# 後手
    
    # 先手の持ち駒 参考 : https://tadaoyamaoka.hatenablog.com/entry/2017/04/08/165742
    hand = board.pieces_in_hand
    hand_b = hand[shogi.BLACK]
    for p in hand_b.keys():
        print("piece: {0}, num: {1}".format(shogi.Piece(p, shogi.BLACK).symbol(), hand_b[p]))
        print("piece: {0}, num: {1}".format(shogi.Piece(p, shogi.BLACK).japanese_symbol(), hand_b[p]))

    print('-'*100)

USI形式について

駒の表記法、位置の表記法についてはこちらをご覧ください
将棋所:USIプロトコルとは

駒の表記法

盤面を表記するとき、1段目の左側(9筋側)から駒の種類を書いていきます。空白の升は、空白が続く個数の数字を書きます。
平手初期局面の場合、1段目は、左から後手の駒が香桂銀金玉金銀桂香と並んでいるので、lnsgkgsnlとなります。2段目は、空白が1升、後手の飛車、空白が5升、後手の角、空白が1升というように並んでいるので、1r5b1となります。

位置の表記法

指し手に関しては、駒の移動元の位置と移動先の位置を並べて書きます。7七の駒が7六に移動したのであれば、7g7fと表記します。(駒の種類を表記する必要はありません。)
駒が成るときは、最後に+を追加します。8八の駒が2二に移動して成るなら8h2b+と表記します。
持ち駒を打つときは、最初に駒の種類を大文字で書き、それに*を追加し、さらに打った場所を追加します。金を5二に打つ場合はG*5bとなります

Python MidoでのMIDIファイル生成方法メモ

Mido

midoはMIDIを扱うことができるpythonライブラリです。
このライブラリを使うことでMIDIファイルの読み書きが可能です。今回はpython3で音を指定してMIDIファイルを作成するmidoの使い方についてメモしていきます。

基本形

まずはこのドキュメント通りに出力して、noteの値を変えて音が変わることを確認してみましょう。
MIDI Files — Mido 1.2.10 documentation
import mido
from mido import Message, MidiFile, MidiTrack

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)

# MIDIの音色を指定
track.append(Message('program_change', program=12, time=0))
# C3(note=60, ド)の音を、指定の音量と時間で再生
track.append(Message('note_on', note=60, velocity=64, time=32))
track.append(Message('note_off', note=60, velocity=127, time=32))

mid.save('new_song.mid')
※Messageに指定する値と範囲はこちらのドキュメントを参照してください。
Message Types — Mido 1.2.10 documentation

テンポを指定するにはset_tempoを使います。4分音符の長さを480tickとして、tick数により長さを指定します。
テンポを指定しつつ、いくつかの音を出してみましょう。
import mido
from mido import Message, MidiFile, MidiTrack, MetaMessage

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)
track.append(MetaMessage('set_tempo', tempo=mido.bpm2tempo(120)))

track.append(Message('note_on', note=60, velocity=64, time=0))
track.append(Message('note_off', note=60, time=480))
track.append(Message('note_on', note=60+4, velocity=64, time=0))
track.append(Message('note_off', note=60+4, time=480))
track.append(Message('note_on', note=60+7, velocity=64, time=0))
track.append(Message('note_off', note=60+7, time=480))

mid.save('new_song.mid')
このような内容のmidiが出力されます。
sample2_midi

和音の出し方

音を重ねるにはこのように指定します。
import mido
from mido import Message, MidiFile, MidiTrack, MetaMessage

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)
track.append(MetaMessage('set_tempo', tempo=mido.bpm2tempo(120)))

track.append(Message('note_on', note=64, velocity=60, time=0))
track.append(Message('note_on', note=64+4, velocity=60, time=0))
track.append(Message('note_on', note=64+7, velocity=60, time=0))
track.append(Message('note_off', note=64, time=480))
track.append(Message('note_off', note=64+4, time=0))
track.append(Message('note_off', note=64+7, time=0))

mid.save('new_song.mid')
sample3_midi

複数のトラックの作成

トラックを複数用意し、それぞれに音を入れていきましょう。
import mido
from mido import Message, MidiFile, MidiTrack, MetaMessage

mid = MidiFile()
track1 = MidiTrack()
track2 = MidiTrack()
mid.tracks.append(track1)
mid.tracks.append(track2)
track1.append(MetaMessage('set_tempo', tempo=mido.bpm2tempo(120)))
track2.append(MetaMessage('set_tempo', tempo=mido.bpm2tempo(120)))

track1.append(Message('note_on', note=64, velocity=60, time=0))
track1.append(Message('note_on', note=64+7, velocity=60, time=0))
track1.append(Message('note_off', note=64, time=480))
track1.append(Message('note_off', note=64+7, time=0))

track2.append(Message('note_on', note=64+4, velocity=60, time=40))
track2.append(Message('note_off', note=64+4, time=480))

mid.save('new_song.mid')

複雑な音階

midoはプログラムの中で扱えるので、このように適当に変数を使いつつ組み立てていくことになるでしょう。今回はバッハ 平均律クラヴィーア曲集 第1巻 みたいな音を作ります。
ただしコードを見て分かるように、読みやすいものを作るのは難易度が高そうです。
import mido
from mido import Message, MidiFile, MidiTrack, MetaMessage

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)
track.append(MetaMessage('set_tempo', tempo=mido.bpm2tempo(120)))

node_time = 480 * 2
node_pos = 60
node_16 = int(node_time/8)

track.append(Message('note_on', note=node_pos, velocity=60, time=0))
track.append(Message('note_on', note=node_pos+4, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+7, velocity=60, time=node_16 ))
track.append(Message('note_off', note=node_pos+7, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+12, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos+12, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+16, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos+16, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+7, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos+7, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+12, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos+12, velocity=60, time=node_16 ))
track.append(Message('note_on', note=node_pos+16, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos+16, velocity=60, time=node_16 ))
track.append(Message('note_off', note=node_pos+4, velocity=60, time=0 ))
track.append(Message('note_off', note=node_pos, velocity=60, time=0))

mid.save('new_song.mid')
このような内容が出力されます。
sample4_midi
これを使った作例がこちらです。
バッハの平均律クラヴィーアみたいのをランダム生成する - えんたつの記録

このようにMidoはプログラムでMidi生成することにも活用できます。

バッハの平均律クラヴィーアみたいのをランダム生成する

 バッハの「平均律クラヴィーア曲集 第1巻 第1番 ハ長調」の冒頭のパターンをランダムに繰り返したらどうなるか?という発想で音楽を生成しました。

・音のパターンは、冒頭に出てくる3パターンの音の動きをランダムに使用しています。
・そのパターンを再生する際の基準となる音は一定範囲内でランダムに生成しています。

 今回の生成結果はこちらです。
 映像はMIDITrailにより生成しています。繋がりの部分は、パターンをもっと都合よく選べばより自然にな流かもしれません。
このサイトについて
Webアプリケーション開発のことや、iPhone・Android向けアプリ開発の話題が中心です。
管理:えんたつ twitter: @tattyamm
mimage
一部のリンクにはアフィリエイトが含まれます。
カテゴリ別アーカイブ
RSS
プログラミング本
古い本含めてメモです
iPhoneプログラミングUIKit詳解リファレンス iPhoneプログラミングUIKit詳解リファレンス Android Layout Cookbook アプリの価値を高める開発テクニック パーフェクトPHP (PERFECT SERIES 3) JavaプログラミングBlack Book 2nd Edition (Black Bookシリーズ)
表記
当サイトではGoogle Analyticsを使用しております。詳細はこちらを御覧ください