shingoushori's dialy

音信号処理を専ら研究していた元博士後期課程の学生によるメモ

PythonでSimutransの全乗り物の待機を上書きしてみた

GUIでぽちぽち1000台以上のバスの情報を設定するのは苦しいので、Pythonでやってみました。
正しくは、とりあえずやれたのが、まずこれだけ。

最大の苦戦どころが、
xmlデータだって言っても、CDATA なるものに対応するのが辛い
 → いっそテキストで全読み込み -> 文字列変換でElement化、パースできるように
というところです。
荒技感が強いですが、数日ググってあれこれやってみて明快な対応しているパーサや設定方法が見当たりませんでした。

さらに、あれこれやるのに苦しそうなのが、xmlデータのElementの要素名が最小限以外ほぼ無意味っぽいってことです。
convoi, haltestelle, fabrik ... あとは i64 とかだらけで、
バイナリから最小限に引っ張り出してきた感満載です。


↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import xml.etree.ElementTree as ET

filename_in = 'test_in.sve'
filename_out = 'test_out.sve'

f = open(filename_in)
data1 = f.read()  # ファイル終端まで全て読んだデータを返す
f.close()

data2 = data1.replace("<![CDATA[","<CDATA>")
data2 = data2.replace("]]>","</CDATA>")

root = ET.fromstring(unicode(data2.encode('utf-8')))

for convoi in root.iter('convoi_t'):
  for fahrplan in convoi.iter('fahrplan_t'):
    fahrplan_iter = fahrplan.iter()
    elemdist = 0
    for elem in fahrplan_iter:
      if elem.tag == "koord3d":
        elemdist = 1
      elif elemdist == 5:
        # 積むまで待機(%)
        elem.text = "10"
      elif elemdist == 6:
        # 最大待ち時間(月)
        # elem.text = "6" # 1/1024
        # elem.text = "7" # 1/512
        elem.text = "8" # 1/256
      elemdist = elemdist + 1

data3 = ET.tostring(root, encoding="utf-8")

data4 = "<?xml version=\"1.0\"?>\n" + data3
data4 = data4.replace("<CDATA>","<![CDATA[")
data4 = data4.replace("</CDATA>","]]>")
data4 = data4.replace("<CDATA />","<![CDATA[]]>")
data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">")
# 元々のセーブデータのバージョンに合わせる

f = open(filename_out,'w') # 書き込みモードで開く
f.write(data4)  # 引数の文字列をファイルに書き込む
f.close()

Simutransで人工地盤してみる

素敵なフリーの輸送会社経営シミュレーションゲーム Simutrans で人工地盤っぽいことを初めてみました。

↓実験の光景↓

白黒の見切れているのが、役場です。
道路や鉄道を引くのに、役場の場所が邪魔になることがあります。
しかし、役場は撤去しないで済むならしたくありません。街もろとも消滅するからです。

そこで、高架橋。上を通すことができます、無理やり感がありますが。
これを発展させて、街を丸ごと上に上げてしまおうというのが、このプレイの発想です。
こういうのを、人工地盤って言ったと思う。

↓例えば、こんな感じ↓

 

さて、人工地盤するのに、追加で以下のアドインを用いました。
・道路関係セット [作者:wa様] アドオン/交通施設 2 - Simutrans日本語化・解説
バラスト・スラブ線路セット [作者:りむ様] アドオン/railtool - Simutrans日本語化・解説
+↑上述2つをベースに自分で改造したもの(柱、低コスト道路...)

ゲーム内ではコストの概念があります。
すると、高架橋は高規格が主なので、高コストな気がして気が引けました。
そこで、柱だけ〜低速用〜のものを自作(改造?)することにしました。
とりあえず、GIMPでガシガシ。

 

さあ、果たして本当に私好みなプレイができるんでしょうか。
高架を積みあげた分のコストが回収できるんでしょうか。。。

PythonでMIDIをWAVにする ...

PythonMIDI をいじってみています。
とりあえず、pretty_midi にしています。

http://shingoushori.hatenablog.jp/entry/2017/06/11/233154

今回は、MIDIをWAVにしてみました。

... 結論
・FluidSynth 頼み
・サウンドフォントっていうのでMIDIをWAVに置き換える
・WAVファイルへの書き出しやらは SciPy で

[FluidSynth]
MIDIをWAVにできそうなあれこれは、いくつか見かけます。
しかし、結局はFluidSynthを呼び出すだけのもの...に見えます。

midi2audio 0.1.1 : Python Package Index

何より、pretty_midi は FluidSynth を使って合成する関数を装備しています。

pretty_midi — pretty_midi 0.2.8 documentation

自由研究の準備(その9)PythonでのMIDI操作(SMF編) - クーの自由研究

ただし、使うのにpyFluidSynth が必要だったような。

pyFluidSynth 1.2.4 : Python Package Index

[サウンドフォント ~ SoundFont]
FluidSynthで置き換えるのに、サウンドフォントが必要だそうだ。

FluidSynth / Wiki / SoundFont

↓ ここのページで色々紹介されていますな。

サウンドフォント | MuseScore

[wav file]
pretty_midi の FluidSynth を使って合成する関数〜の出力は、np.ndarray らしい。
... で np.ndarray をwavファイルに書き出す方法で手軽そうだったのが、
scipy.io.wavfile.write かなと。

scipy.io.wavfile.write — SciPy v0.19.1 Reference Guide

...
こんな感じで地味にめんどくさいですね。
準備ができれば数行で終わってしまうので...まあ。

出来上がったWAVファイルは、懐かしい感じのMIDIらしい音でした。
np.ndarray なので、いよいよ信号処理です。

Pythonで楽曲のスペクトルの動画の作成 のメモ

以下が構成するモジュールとかアプリケーション
・matplotlib
imagemagick
FFmpeg
PyAudio
・NumPy

以下のページのサンプルが素敵
Frequency spectrum of sound using PyAudio, NumPy, and Matplotlib · GitHub

matplotlibがmp4が描き出せるというのが、
楽曲のスペクトルでなくとも、手軽そうで素敵です
matplotlib でアニメーションを作る - Qiita

しかし、悲しいことにこれだけだとうまくいきませんでした
Mac特有の問題と記事の時期とのズレが問題かと

まず、Macだとmatplotlibがいうことを聞いてくれないので、
以下のページを参考に、設定ファイルmatplotlibrcを書き換えました
matplotlibで簡単にアニメーションをつくる(mp4, gif) - Qiita
pyenvとvirtualenvで環境構築した時にmatplotlib.pyplotが使えなかった時の対処法 - Qiita

次に、FFmpegです
サンプルだと -acodec libmp3lame となっていますが、これが通らず
mp3のエンコーダー lame が未インストールだからだろうと推測しつつ
以下のページに倣って、 -acodec aac としたら通りました

http://dev.classmethod.jp/etc/ffmpeg-create-movie-by-audio/

Pythonでプロトタイプするときはモジュール化しておこう...

Pythonでプロトタイプするときはモジュール化しておこう...
と思った

とりあえず、main でも test でもなんでもいいから関数化しておくだけでも
随分違いそうなことがわかった

今、PythonでMIDIをいじってみています
ちょっとしたパターンを生成するソースは、まぁ、すぐにできました
となれば、それを再利用したり、ガリガリ大量生産してみて、
「ふむ」と言ってみたくなります

ここで、じゃあそれをせっかくだからPythonでやろうと思ったわけです

スクリプトファイルとモジュール化 — PyCon JP 2012 Pythonプログラミングハンズオン(初級者向け) documentation

シェルでスクリプトそのものを動かす、引数入れ替えるだけー...よりは、
ちょっと面倒だけれども、モジュールとして関数をガリガリ再利用できるのは、
ソースコードさえ、再利用に耐えうる書き方をしておけば、全然素晴らしいですね!

Pythonの利点もイマイチわからないし、
そもそもPythonがなんなのかわからないけれども
身近なPythonianからは、シェルを使っていると「Pythonスクリプトだから、もともとそういうのもPythonが得意なはずだから、Pythonでやりなよー」と啓蒙されてきました
その良さの一端を垣間見た気分です

Canvas関係のグラフを描くライブラリを使ってみた

<概要>

Canvasの練習です.
前回、"Canvasで、任意長の配列で折れ線を描いてみる"してみました.
次は、軸を描いてみて、グラフにしたいと思ったわけです.
そういえば、ライブラリが無いわけがないと思いまして、探して使ってみました.

今回使ってみたのは、次の2つ.
Chart.js
CanvasJS
他にも色々ある中でこれらに目をつけたのは、とりあえずはフリーだから.
それでいて、比較的データ自体の入力以外が少なそう...と思ったから.
しかし、いざやってみると細々としたオプションを設定したくなってしまったのでした.
↓とりあえず、同じデータで同じようなオプションを設定してみました↓


・Chart.js

・CanvasJS

 

Chart.jsは、凡例をクリックしたらそのデータの表示がトグルできるんですね!デフォルトで!これは素敵です.
しかし、デフォルトで表示時のアニメーションと線の下の塗りつぶしがついているのはイマイチです、チャーミングですけれども。
また、デフォルトで折れ線部分が丸くなるんです.これを外すのにしばらく悩みました.

CanvasJSは、とりあえず凝ったことをやろうとしたら有料らしいです.怖くて使いづらいです.
データ入力が単純な配列じゃなくて、{y:value}って具合にいちいち格納しないといけません.特定の値だけにlabelをつけられるのは良さそうですが.
今回はまだ使っていませんが、Spline Chartが用意されているのが気になるところです.

<結論>

どちらを使っていくのか全然悩む程度には、どちらも今ひとつでした.

<参考文献>

Chart.js | Open source HTML5 Charts for your website

【Chart.js】折れ線グラフの色設定

Beautiful HTML5 JavaScript Charts | CanvasJS

JavaScriptで爆速グラフ・チャートが作成できる「CanvasJS」を使ってみた! : うえぶはっく

Canvasで、任意長の配列で折れ線を描いてみるテスト

<概要>
Canvasの練習です.
任意長の配列で折れ線を描く.これを関数したら楽にならないかな、と思っている次第であるためです.

やってみた事は単純です.
1.座標点の配列を定義
2.配列の各点を、canvasの折れ線の終点として次々に設定 : context.lineTo
3.ついでに各点の座標点に、塗りつぶした円を点として設定

やってみて意外だったのが、起点の座標の設定 context.moveTo が省けてしまった事です.
起点を設定せず、最初の終点として起点を設定しています.


<参考文献>
canvasを使ってグラフを描く - Webサイト制作最新トレンドの傾向と対策 | Webデザインとグラフィックの総合情報サイト - MdN Design Interactive