MIDIシンセサイザTiMidity++で扱えるGUS patch形式の音源である “Eawplus” についてを扱う。
元の記事は2007年6月と2008年3月に書かれたが、自動でファイルをダウンロード・展開するスクリプトを追加するなど一部内容を書き直している。
Eawplusについて
GUS patch形式の音源の中では高品質な “Eawpatches” をベースとして “出雲パッチ” と呼ばれる音源と幾つかの追加ファイル群を加えて調整し直した音色セットで、同形式の音源としては最も優れたものとなっている。
どちらの公式サイトも閉鎖されており、現在はアクセスできない。
TiMidity++で使用する設定ファイル(-c
オプションで場所を指定)はtimidity/timidity.cfg
として配布ファイルの中に含まれているが、環境(配置場所)に応じて “dir
” の行を編集する必要がある。
ファイルのダウンロード
ファイルのダウンロードは上記のWayback Machine上のページからも行えるが
- EawpatchesはGentoo Linuxのミラーサーバ(tar.gz形式で配布)
- 出雲パッチとEawplus用追加パッチはFreeBSDのミラーサーバ
にもそれぞれ存在するため、直接取得することもできる。
ファイル名 | 説明 |
---|---|
eawpats12_full.tar.gz | Eawpatches(Eric氏による) |
guspat-20000706-required.tar.gz | 出雲パッチ(出雲氏による)の基本ファイル群 |
guspat-20000706-optional.tar.gz | 同パッチの追加ファイル群 |
eawplus-12.1.tar.gz | Eawplus用の追加パッチ(田向氏とSYUUHOU氏による) |
Eawpatches本家配布のファイルはRAR形式なので、GNU/Linuxでは展開にunrar
が必要。
ダウンロードと展開を自動化するPythonスクリプト
下のスクリプトを保存し、実行属性を付けてPython 3で実行すると、上記のファイル群をミラーサーバから全て自動的にダウンロードして、引数に指定したディレクトリ(要書き込み権限)以下にこれらを展開する。サーバからのダウンロードに失敗した場合はWayback Machine上のURLからのダウンロードを試みる。
--update-cfg
(-u
)オプションを付けて実行すると、展開後にtimidity/timidity.cfg
のdir
行を書き換えて、そのままの場所で(TiMidity++から-c
オプションで.cfgファイルの場所を指定するだけで)音源データが使用可能になり、更にEawpatches単体で使いたい場合向けのeawpats/timidity.cfg
も同様に書き出す。
処理は全てPythonの標準機能で行っており、外部コマンドは使っていない。
プロキシサーバを使用している環境では小文字の環境変数http_proxyにサーバURLを指定して実行する。
get_eawplus.py
ライセンス:MIT#! /usr/bin/python3
# get_eawplus.py - Download/extract "Eawplus" GUS patch set
# (Eawpatches + Izumo [required + optional] + Eawplus)
# (C) 2017 kakurasan
# Licensed under MIT
from urllib.request import urlopen
import optparse
import tempfile
import tarfile
import locale
import shutil
import errno
import sys
import os
version = '20170430'
g_src = ('http://gentoo.gg3.net/distfiles/eawpats12_full.tar.gz',
'http://distcache.freebsd.org/local-distfiles/nork/guspat-20000706-required.tar.gz',
'http://distcache.freebsd.org/local-distfiles/nork/guspat-20000706-optional.tar.gz',
'http://distcache.freebsd.org/local-distfiles/nork/eawplus-12.1.tar.gz')
class OptParser (optparse.OptionParser):
_opts = \
(
optparse.make_option ('-u', '--update-cfg', dest = 'update_cfg', action = 'store_true', help = 'update .cfg files for TiMidity++', default = False),
)
_config = \
{
'usage' : '%prog (-u/--update-cfg) (DIRECTORY)',
'version' : '%prog ' + version,
'option_list' : _opts
}
def __init__ (self):
optparse.OptionParser.__init__ (self, **self._config)
class Unsuccessful (Exception):
def __init__ (self, message):
self._message = message
def __str__ (self):
return self._message
def download_file (url, filename, fallback = False):
print ('Downloading {0}{1} ...'.format (url, ' (fallback)' if fallback else ''))
try:
f_url = urlopen (url)
try:
with open (filename, 'wb') as f_out:
while True:
buf = f_url.read (8192)
if not buf:
break
f_out.write (buf)
finally:
f_url.close ()
except IOError as e:
if not fallback:
return download_file ('http://web.archive.org/web/' + url, filename, fallback = True)
else:
return 'Could not download "{0}": {1}'.format (url, e)
def main ():
locale.setlocale (locale.LC_ALL, '')
opt_parser = OptParser ()
options, args = opt_parser.parse_args ()
if len (args) > 0:
outdir = args[0]
try:
os.makedirs (outdir)
except OSError as e:
if e.errno != errno.EEXIST:
return 'Could not create directory "{0}": {1}'.format (outdir, e)
try:
os.chdir (outdir)
except OSError as e:
return 'Could not move to directory "{0}": {1}'.format (outdir, e)
tempdir = tempfile.mkdtemp ()
try:
for url in g_src:
filename = os.path.basename (url)
filepath = os.path.join (tempdir, filename)
# Download
error = download_file (url, filepath)
if error:
print ('Download failed.')
raise Unsuccessful (error)
# Extract
print ('Extracting {0} ...'.format (filename))
try:
with tarfile.open (os.path.join (tempdir, filename), 'r|gz') as f_tar:
f_tar.extractall () # Some files are not extracted if Python 2 is used
except Exception as e:
raise Unsuccessful ('Could not extract file "{0}": {1}'.format (url, e))
print ('Deleting {0} ...'.format (filename))
os.unlink (filepath)
# Update .cfg files if the option '-u' ('--update-cfg') is specified
if options.update_cfg:
# Write timidity.cfg for Eawpatches
cwd = os.getcwd ()
cfg_path = os.path.join ('eawpats', 'timidity.cfg')
print ('Writing {0} ...'.format (cfg_path))
try:
with open (cfg_path, 'w', encoding = 'ascii') as f_out_cfg:
f_out_cfg.write ('dir {0}\n'.format (os.path.join (cwd, 'eawpats')))
for name in ('gravis', 'gsdrums', 'gssfx', 'xgmap2'):
f_out_cfg.write ('source {0}.cfg\n'.format (name))
except IOError as e:
raise Unsuccessful ('Could not write to file "{0}": {1}'.format (cfg_path, e))
# Update timidity.cfg for Eawplus
cfg_temp_path = os.path.join (tempdir, 'timidity.cfg')
cfg_path = os.path.join ('timidity', 'timidity.cfg')
print ('Updating {0} ...'.format (cfg_path))
try:
with open (cfg_path, 'r', encoding = 'ascii') as f_in_cfg:
with open (cfg_temp_path, 'w', encoding = 'ascii') as f_out_cfg:
for l in f_in_cfg:
if l.startswith ('dir '):
l = l.replace ('/usr/share/timidity/eawpats', os.path.join (cwd, 'eawpats'))
l = l.replace ('/usr/share/timidity', cwd)
f_out_cfg.write (l)
os.unlink (cfg_path)
shutil.move (cfg_temp_path, 'timidity')
except IOError as e:
raise Unsuccessful ('Could not update file "{0}": {1}'.format (cfg_path, e))
except Unsuccessful as e:
return e
finally:
print ('Deleting temporary directory ...')
shutil.rmtree (tempdir)
print ('Done.')
if __name__ == '__main__':
sys.exit (main ())
実行例(現在の階層にeawplusディレクトリを作ってその中に配置する・設定ファイルを更新) $ /path/to/get_eawplus.py -u eawplus (現在の階層に直接配置する・設定ファイルは更新しない) $ /path/to/get_eawplus.py
全ての処理に成功すると、配置ディレクトリには以下のディレクトリが生成される。
ディレクトリ | 説明 |
---|---|
doc | ドキュメント類(動作には必須ではない) |
eawpats | Eawpatches |
timidity | 出雲パッチとEawplus |
- Python 3.5.3
- TiMidity++ 2.13.2