« デジタルガジェット音比べ 周波数特性計測(999円プレイヤーDN-2000/Zaurus SL-C3200/SigmarionIII/iPod等) | Main | Cygwin/i386 Linux用Windows CE(PocketPC)クロスコンパイラCeGCCを試す »

2006.10.03

ZaurusでMIDI制作 Z-MUSICコンパイラzmc3と標準MIDIファイルコンバータz2m3のZaurus向けパッケージ

テキストで書いたZ-MUSIC v3形式の曲データから標準MIDIファイルを生成するツールである、わいやぎさん作zmc3とz2m3のLinux Zaurus向けパッケージを作りました。不具合が無い限り、非公式最新版を使うのがよろしかろうと思います。

zmc3

非公式最新版(評価未完): zmc3 v0.98.10 (May 27th, 2006)

「zmc3_0.98.10_arm.ipk.bin」をダウンロード

安定最新版: zmc3 v0.97 (Jan. 27th, 2003)

「zmc3_0.97_arm.ipk.bin」をダウンロード

z2m3

非公式最新版(評価未完): z2m3 v1.27 (May 12th, 2006)

「z2m3_1.27_arm.ipk.bin」をダウンロード

安定最新版: z2m3 v1.19 (May 29th, 2002)

「z2m3_1.19_arm.ipk.bin」をダウンロード

使い方

テキストエディタでZ-MUSIC v3仕様のソースコードを書き、zmc3コンパイラにかけ、さらにz2m3コンバータにかけます。

zmc3 test.zms; z2m3 test.zmd

これで標準MIDI形式のtest.midが出来ます。簡単。
出来たmidファイルをtimidityで再生すれば、Linux Zaurus上で曲データ作成から再生まで通しでできます。

Z-MUSIC v3とは?

わいやぎさんの書かれた「Z-MUSICとは?」を読んでいただくのが一番ですが、かいつまんで説明します。

Z-MUSICは、かつて一世を風靡したSHARPのパソコン (Personal Workstation) X68000シリーズで広く使われた「X680x0用内蔵音源(FM音源とADPCM音源)/MIDI音源制御システム」です。

それを汎用化したものがzmc3です。オリジナルのZ-MUSICは音源ドライバとコンパイラで構成されていましたが、zmc3はZ-MUSIC v3仕様のMMLをzmd形式へコンパイルするコンパイラです。zmc3からはオリジナルにある機種依存(FM音源やADPCM音源の制御)部分は削除されています。ドライバはありません。

zms、zmd形式のデータを直接再生するプレイヤーというものも存在しますが、普通はz2m3を使ってzmdファイルからmidファイルを作ります。
標準MIDIファイルを最終生成物、zmdは中間ファイルとして扱うでしょう。
だから、現在の認識としては標準MIDIファイル作成環境、ということでいいかと思います。

Z-MUSIC v3仕様のソースコードとはどんなものか。以下のようなものです。

[volume 127] [velocity 127]

abcfgab

いわゆるMMLですね。BASICを知っている人なら、PLAY文が高機能化したものと思ってもらうのがいいでしょう。

MMLから標準MIDIファイルを生成する環境は他にもありますが、Z-MUSICは、元来の高機能に加え、わいやぎさんの手による効率化、便利化がハンパでなく、いまだ存在意義を残しています。
ほかの処理系との比較を前述のわいやぎさんのページで行なっていますので、読んでみると面白いと思います。

X68000の血脈を継ぐと勝手に思っているLinux Zaurus上でZ-MUSICが動くことには、ある種の人々にとって特別な感慨があることと思います。

注意点

Linux Zaurus向けのバイナリについての質問を、作者であるわいやぎさんに直接送らないようにしてください。

ただ、zmc3/z2m3そのものにも不完全な部分はあり、現在進行形でメンテナンスされています。
Linux Zaurus向けバイナリで出た問題が、もし公式に配布されているWin32版でも出るようであれば、以下のZ-Music BBS等へ連絡してみてはいかがでしょうか。

Z-Music BBS

わいやぎさん、バイナリ配布にご快諾いただき、ありがとうございます。

備考

Linux Zaurus向けにビルドする際、ソースコードをnkf --unixでEUC-jp/LFに変換しました。
これをやらないとビルドできませんでした。
このことに伴い、コマンドヘルプはEUC-jpで表示されます。

CFLAGSに-fsigned-charを加えてビルドしています。

warning: comparison is always true due to limited range of data type

がたくさん出たからです。

Emacs用のZ-MUSIC編集モード

やっぱりZ-MUSIC用のメジャーモードがあります。
wabeeさんのz-music-mode.elです。それを使うと編集が楽になります。
各種編集支援機能のほか、Emacsからzmsのmidファイルへのコンパイル、midファイルの再生、ストップができます。

wabeeさんのZ-MUSICの解説も分かりやすいです。

timidityと組み合わせて使う場合の.emacs.elの設定

(load-library "hilit19")
(load-library "zmusic-mode")
(add-hook 'zmusic-mode-hook
(function (lambda () (hilit-highlight-buffer))))
(setq zmusic-playmidi-term-command "killall timidity")
(setq zmusic-playmidi-device "")
(setq zmusic-shell-filename "bash")
(setq zmusic-playmidi-command "timidity")
(setq zmusic-playmidi-option "")
(setq auto-mode-alist (cons '("\\.zms\\'" . zmusic-mode) auto-mode-alist))

SIGSTOP問題の回避

Zaurusでzmusic-modeを使う場合にはSIGSTOPが問題になってきます。
zmusic-shellとしてシェルを動かしているからです。
サスペンドさせ、次にレジュームしたときにはshellがstopしてしまいます。

これによって、レジューム後にtimidityでの再生関連機能が動かなくなります。
スペシャルカーネルを入れる、SIGSTOP対策済みシェルを使うなどしていない場合は、zmusic-mode.elのzmusic-shell関連の関数に修正が必要です。

具体的には、zmusic-term-playmidiとzmusic-playmidiを以下のように修正します。
from hereからto hereまでを挿入します。
SIGSTOPでシェルがstopしている場合はプロセスを殺しています。

zmusic-playmidiでは、timidityで再生中だった場合には、併せてtimidityをkillしてます。
これにより、zmusic-playmidiによってコンパイルしたmidiデータのプレビュー中に再度zmusic-playmidiを実行した場合には、頭から再生し直す動作としています。

(defun zmusic-term-playmidi ()
"略"
(interactive)
;; from here
(if (and (get-process "zmusic-shell")
(eq (process-status (get-process "zmusic-shell")) 'stop))
(delete-process "zmusic-shell"))
;; to here

(defun zmusic-playmidi ()
"略"
(interactive)
;; from here
(if (not (string= (shell-command-to-string "ps ax | grep timidit[y]") ""))
(shell-command "killall timidity"))
(if (and (get-process "zmusic-shell")
(eq (process-status (get-process "zmusic-shell")) 'stop))
(delete-process "zmusic-shell"))
;; to here

画面が狭いため、コンパイル時のメッセージ表示Windowを、Errorが無い時には消す関数を書いてみたのですが(きっと同じことを思う人は多いでしょう)、うまく動かせてません……。
単体で実行するとうまく動くものの、zmusic-run-compileの中から実行するとうまく動きません。

2006.10.7追記:うまく行かない理由が分かりました。compile関数が非同期実行だからですね。コンパイルが終わる前に見に行ってしまう。こういう場合は、変数compilation-finish-functionにb rを引数に取るラムダ式を代入しておくと、compile関数終了後に自動実行してくれるようです。これで希望の動作ができました。

(setq compilation-finish-function
(lambda (b r)
(progn
(let ((compile-window-name "*compilation*")
(compile-window-error-keyword-regexp "Error"))
(if (bufferp (get-buffer compile-window-name))
(progn
(set-buffer compile-window-name)
(goto-char (point-min))
(if (not (re-search-forward compile-window-error-keyword-regexp nil t))
(if (windowp (get-buffer-window compile-window-name))
(delete-window
(select-window
(get-buffer-window compile-window-name)
))
)
(display-buffer compile-window-name)
)
)
)
))
))

zms2mid

zmusic-modeでは、zmsをmidに変換するコマンド、zms2midがあることが前提となっていますので、書きます。zmc3でzmsからzmdに、z2m3でzmdからmidに変換するので、それを橋渡ししてやるスクリプトを書くわけですね。これをパスの通ったところに置きます。

#!/bin/sh

#///////////////////////////////////
#
# zmc3 / z2m3 helper script
#
#///////////////////////////////////

##################################
# help
##################################

if [ "$1" = "" ]; then
echo "usage: zms2mid [source file name (without extension name)] [option]"
echo ""
echo "Option:"
echo " clean delete [source file name].zmd and [source file name].mid."
echo ""
return 0;
fi

if [ ! -f "${1}.zms" ]; then
echo "ERROR: source file not found."
return 1;
fi

##################################
# clean
##################################

if [ "$1" != "" -a "$2" = "clean" ]; then
if [ -f ${1}.zmd ]; then
rm ${1}.zmd
if [ $? = 0 ]; then
echo "delete ${1}.zmd"
fi
fi

if [ -f ${1}.mid ]; then
rm ${1}.mid
if [ $? = 0 ]; then
echo "delete ${1}.mid"
fi
fi

ls -l ${1}.zms

return 0;
fi

##################################
# zms -> zmd
##################################

zmc3 $1
if [ ! $1 ]; then
echo "ERROR: zmc3 failed."
return 1;
fi

##################################
# zmd -> mid
##################################

z2m3 $1
if [ ! $? ]; then
echo "ERROR: z2m3 failed."
return 1;
fi

ls -l ${1}.zms ${1}.zmd ${1}.mid

|

« デジタルガジェット音比べ 周波数特性計測(999円プレイヤーDN-2000/Zaurus SL-C3200/SigmarionIII/iPod等) | Main | Cygwin/i386 Linux用Windows CE(PocketPC)クロスコンパイラCeGCCを試す »