2014-08-15
マリオシーケンサをポケミクに対応した
先日、公開したマリオシーケンサのWebアプリですが当初から本当の目的はポケミクに歌わせることでした。
思えば4月?にポケミクが出ると同時に買って以来、何をしようか考え始め、Web MIDI API周辺を調べ始めたのが発端でした。
ポケミクをもっと簡単に歌わせたい、しかし私には音楽の才能が無い、どうしようかと考えたのです。
マリオシーケンサを思い出すのは時間がかかりませんでした。
マリオシーケンサのMSQファイルの構造は非常に簡単で解析に時間はかかりませんでした。
マリオシーケンサにはFの音しか入っておらず変調して用いるのは直ぐに想像できました。
そこからWeb Audio APIを勉強し始め、HTML5Rocksを読んだり、O'Reillyの本が運良くWebで公開されていたのを全部読んだりなどしてWeb Audio APIと以前に学んだCanvasでマリオシーケンサをWebアプリにすることは可能だと睨んだのが4月終わりから5月くらいだったのでしょうか。そこからは一月あっという間でした。とりあえずWAVのみ版を公開したのが5月26日でした。
で、7月、8月も半分づつ1月この件に打ち込んだ結果がこれです。相変らず前振が長い (^^;
http://minghai.github.io/MikuMikuSequencer/?url=NikoNiko_suite.json&auto=true
https://github.com/minghai/MikuMikuSequencer
名前はMiku Miku Sequencerに変えてあります。
あのMMDにあやかっている様ですが、実際にはポケミクシーケンサと名付けようとしていた所、既にその名前でプログラムを作成している方がいらしたという理由もありました。
本人が恥しくて、あまりこの名前を口にしていません(笑
(注意) 相変わらずChromeでしか動きません。Firefoxでは謎のエラーが出るのでとりあえず放ってあります。ChromeならAndroidでも動いています。
ポケミク対応版を実行するにはポケミクを接続することが必須なのでYoutubeで公開した録画を置いておきます。
使い方
まずは次のチュートリアルビデオを参照して下さい。
はてな日記の組込画面では小さいのでできればYoutubeで別画面として開いて見て下さい。
上の組込ビデオのYoutubeのロゴを押すとYoutubeサイトで開き直すことができます。
ご覧の通り、基本的な使い方は非常に簡単です。
WAVかMIDIの音色で曲を完成し、ミクの音を載せて歌詞をテキストエリアに入力すればそのまま歌います。
ただし、以前のマリオシーケンサに比べ、MIDI音源を利用しているため以下の制約があります。
- MIDI音源は減衰が非常に小さい、または減衰しない場合があり、音が無限長になります
- MIDI音源でもキャンセルは効かしてあります。しかし音が連続しない場合にキーオフの指定が必要です
- ミクは同時に一音しか発声できません。これはポケミクの現状の制約です
- MIDIのチャンネル1から15がそのまま音色選択にマッピングされています
- MIDIチャンネルの音色は後述のコマンドを用いて変更が可能です
- MIDIのチャンネル1はミク専用で変更できません
- MIDIのチャンネル10はドラムマップ専用で変更できません
- MIDIのキーは画面上の一番低いド(C4)が60です
- MIDIのチャンネル10(ドラムマップ)のみ一番低いB3がキー35にマップされます。これはドラムを優先するためです。
上記の制約の一部に対応するために、MMSではキーボードとマウスを用いて個別の音に属性を与える必要があります。
音の属性
音には現在、以下の属性が存在します。
- 長さ
- 長さで最も良く使用するのは実際にはキーオフの機能が当てられた長さ0です。デフォルトは無限長でキーオフしなければ音が止まりません。残りはスタッカート用の0.5です。
- オクターブ
- 音の高さは楽譜上の位置で決定しますが、楽譜の領域を越えた高さが必要な場合にはオクターブを相対的に指定します。現在の位置から上下にオクターブを設定可能です。
- 半音
- 音には半音の上げ下げが指定できます。ただし、EとFやBとCのように間に半音が存在しない場合には音の位置がずれる場合があります。
音の属性としては後はボリューム(MIDIの属性としてはvelocity)の実装が考えられますが、現在は実装されておりません。
ミクのみには音の属性としてフォネティックシンボル(Phonetic Symbol)が歌詞として別に与えられ、各音に異なった発声が行われます。
キーボード
以下、使用するキーについて説明します。
- PgUP, PgDn or [,] or I,O
- 楽譜を前、または後ろに1ページめくる
- <,> or ←,→
- 楽譜を棒1本左右にずらす
- w
- (音にカーソルを合わせた状態で)長さ0、またはキーオフの指定
- e
- (音にカーソルを合わせた状態で)長さ0.5、staccato
- q
- (音にカーソルを合わせた状態で)長さ指定の取消
- +,-
- (音にカーソルを合わせた状態で)オクターブを1つ上げる、または下げる
- Shift
- (楽譜に音を置く時に左クリックと同時に押すことで)音を半音上げる
- Ctrl
- (楽譜に音を置く時に左クリックと同時に押すことで)音を半音下げる
- T
- テストプレイ。画面上に表示されている音のみを演奏します
- Shift+T
- テストプレイ。画面上に表示されている音から継続して終わりまで演奏します。画面上のSTOPボタンを押すことで止められます
音にカーソルを合わせた状態は、マウスで赤い四角形のカーソルを楽譜上の音の四方にきちんとはまるように位置して下さい。
正しく実行できればクリック音が鳴り、音には属性が表示されるようになります。
オクターブの上げ下げは楽譜上で表示できる場合には属性の変化ではなく位置の変化として表われます。
音の半音上げ、下げはEとF、BとCの間では位置の変化として表われる場合があります。
歌詞
歌詞の入力は画面右側のテキストエリアに必ず「ひらがな」で入力します。
歌詞の入力にはミクを歌わせたい意図のとおりに入力しなければなりません。
例えば
- まばたきしては → まばたきしてわ
- いきたい → ゆきたい
等が挙げられます。
歌詞の入力にはポケミクで定められた決められた文字しか利用できません。
以下の128文字が入力可能です。
引用元:http://www.din.or.jp/~boya/eVocaloid/pokemiku.html
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | あ | い | う | え | お | か | き | く | け | こ | が | ぎ | ぐ | げ | ご | きゃ |
1 | きゅ | きょ | ぎゃ | ぎゅ | ぎょ | さ | すぃ | す | せ | そ | ざ | ずぃ | ず | ぜ | ぞ | しゃ |
2 | し | しゅ | しぇ | しょ | じゃ | じ | じゅ | じぇ | じょ | た | てぃ | とぅ | て | と | だ | でぃ |
3 | どぅ | で | ど | てゅ | でゅ | ちゃ | ち | ちゅ | ちぇ | ちょ | つぁ | つぃ | つ | つぇ | つぉ | な |
4 | に | ぬ | ね | の | にゃ | にゅ | にょ | は | ひ | ふ | へ | ほ | ば | び | ぶ | べ |
5 | ぼ | ぱ | ぴ | ぷ | ぺ | ぽ | ひゃ | ひゅ | ひょ | びゃ | びゅ | びょ | ぴゃ | ぴゅ | ぴょ | ふぁ |
6 | ふぃ | ふゅ | ふぇ | ふぉ | ま | み | む | め | も | みゃ | みゅ | みょ | や | ゆ | よ | ら |
7 | り | る | れ | ろ | りゃ | りゅ | りょ | わ | うぃ | うぇ | うぉ | ん\ | んm | ん | んj | んn |
上と左の数値は内部的にどのような数値に変換されるかを示すものですので無視して大丈夫です。
この表を見るとおわかりになるかと思いますが、普通のひらがなの順と違います。
例えば「し」は「すぃ」を使うことが適切な場合が多くなります。
しかし、多くの場合はどちらを使ってもあまり違いがわからないので最初の内は気にせずとも良いかと思います。
また「を」が無く「うぉ」を使わなければならないのですがプログラム内部で書き換えているため「を」を使用して頂いてかまいません。
同様に「づ」が無く「どぅ」を使わねばなりませんがプログラム内部で書き換えているので「づ」を使用して頂いてかまいません。
ポケミクでは同じ字が続く場合には子音が発音されないという仕様があります。
例えば「こころ」はそのまま歌わせると「こおろ」と発音されてしまいます。
しかしプログラムで勝手にキーオフを挿入するので気にせずとも大丈夫です。
「ん」に関しては本来は5種類もあり使い分けの方法は厳しくポケミク内蔵のワンチップVocaloidのNSX-1仕様書P34にて定義されています。
http://yamaha-webmusic.github.io/nsx1-apps/specs/ANMW820A-001-10-j.pdf
しかし現状のこのプログラムではその使い分けがパーザ内部で定義されていないので「ん」(N)しか使えません。
(その内実装したいと思います。すみません :-)
複数の文字をまとめる
歌詞入力で文字を()ではさむと一音に複数の文字を載せることが可能になります。
例えば「(こん)にちは」は5音ではなく4音になります。
特に「ん」の文字は1つの音を割り当ててもらえない場合が多いので多用することになります。
しかし右隣が空いている場合には音を並べたほうが良い場合も多いので色々と試してみて下さい。
現在、既知のバグとして()でまとめた音が歌詞スロットの64文字境界をまたぐとバグります。(--;
申し訳ございません。その内、多分、直します。
()の中では()をネストして利用することはできません。
また次の{}による歌詞の予約も利用できません。
歌詞を予約する
ポケミクのハードウェアには歌詞スロットが16個用意されており、各スロットには64文字を記憶させることができます。
そのため1024文字が利用できるのですが、このプログラムでは直ぐに内容が壊れるインメモリスロットであるスロット0を使用するのを避けています。
このため最大では歌詞が960文字になります。
このままでは組曲のような大物が扱えないため、歌詞を予約という形で保存しておき後述のコマンドにて利用することが可能です。
ただし、歌詞のポケミクへの書き込みは1スロットで平均220[ms]の時間がかかり、最大では3.3秒強の時間の間、MIDIが利用できなくなります。
組曲では歌詞の無い間奏時間が十分にありましたが、制約の強い機能であることをご理解の上、ご利用下さい。
歌詞の予約は簡単で{}で囲まれた歌詞は再生ボタンを押した時点ではポケミクに書き込まれずPCのメモリに記憶されます。
{}で囲んで歌詞は出現順に番号が0から付けられ、後述のコマンドでポケミクに書き込むことが可能です。
{}の中では()を利用することは可能です。
{}の中で{}をネストして利用することはできません。
コマンド
コマンドは歌詞の中に記述します。
歌詞は1行毎に再生時にパースされますが@と#で始まる行はコマンド宣言と見做され歌詞には含まれません。
@は何本目の棒で実行するかを指定します。通常の楽譜のエディット時には何小節目であるかが数字で楽譜の上に表示されています。この小節番号は
1で始まりますが、@で指定する棒番号は0から始まります。従って小節番号から1を引き4(または3/4表記の場合には3)をかけた数字がその小節の棒番号になります。
棒番号はもちろん小節の中でも指定できます。
#はコマンドの開始を宣言します。コマンドはコマンド名と引数から成り立ち、コマンドと各引数の間は空白で区切らなければなりません
現在はコマンドには以下のものが存在します。
コマンド名 | 説明 |
---|---|
ChangeSlot | 正の整数を引数として1つ取り現在の歌詞スロットを指定されたスロットに移動させます。歌詞の位置はそのスロットの先頭になります |
ChangeLyricPosition | 正の整数を引数として1つ取り現在の歌詞スロット内部での位置を指定します。0から始まり63までとなります |
WriteReservedLyrics | 予約した歌詞をポケミクに書き込みます。歌詞の書き込み終了を確認しないため、歌詞の書き込みに十分な時間を考慮する必要があります |
ChangeProgram | 正の整数を2つ引数としてとります。第1引数にはチャンネルを、第2引数にはプログラムを指定します。GM音源仕様書を確認して下さい |
コマンドの使用例
@1424 #WriteReservedLyrics 0
棒番号1424にて予約された歌詞0番をポケミクに書き込みます。
#ChangeProgram 1 127
棒番号が指定されていない場合にはコマンドは再生開始時に全て実行されます。この場合には再生開始時にチャンネル"2"が127(拳銃の発砲音)に設定されます。
チャンネルの設定は0からの指定になることに注意して下さい。
英語
ポケミクは初音ミクv3と異なり英語の発音には対応しておりません。
NSX-1モードで子音だけが発音できるのかどうか試していないのですが、もし可能なら、プログラムをポケミクモードでなく、NSX-1互換モード対応に書き直せば少しはマシになるかもしれません。
現在のポケミクでは英語の歌詞を歌わせようとするとダサダサになるので注意が必要です。
一音毎にボリュームを設定すれば少しはマシになるかもしれませんが、、、、
ちょっと良くわからないので放棄です。
最後に英語の調教を投げ出した悪い例 (^^;
既知のバグ
- テストプレイ時に歌詞の書き込みをpromiseで待っていないために歌詞の位置指定に失敗する場合があります。
妥協策としてShift+Tでなく、まずTを使用し、コンソールログを見ながら歌詞書き込みを待ち、歌詞書き込みが終了してから改めてShift+Tを開始することが挙げられます。
再生時にはこの問題は発声しません。
- スロットの64文字境界で()による分割がまたぐと発声に失敗する
原因はわかっており、対策も取れるのですが、放ってあります(^^;
とりあえず音数を調節してそこで発声しないように回避が可能です。
- スロットの変更に失敗する
プログラムは文字数を数えて自動でスロットを変更するため通常は問題がないのですが、原因不明で20回か30回に一回くらいの確率でスロットの変更に失敗する場合があります。
全く同じデータで成功する場合と失敗する場合があるためポケミク側の挙動の問題ではないかとも想像していますが、これだけは原因がわかりません。
今の所諦めるしかありません。
- 再生後にミク音を曲の途中に置く場合、歌詞の発生が正しくない
これは原因もわかり対策も取れるのですが、テストプレイすれば正しい位置で再生できる(ただし、歌詞書き込みが行われる場合に上記のバグが発生する)のでまだ直してません。
その内、直します(!?)
- 再生後にミク音を曲の途中に置く場合、歌詞の表示が正しくない。
これも上とほぼ同様です。
データ構造
楽譜のデータは全てCurScoreというグローバル変数に入っています。
楽譜の保存をSAVEボタンで行う場合にもこの変数をJSONにしてダウンロードさせているだけです。
CurScoreの重要な属性値について説明します。これを理解した上で使用すれば、デバッグコンソールから直接楽譜を編集することも可能になるため楽譜の小節毎のコピペ等をJavaScriptで行うことが可能になります。
notes
CurScore.notesは楽譜データそのものです。notesは配列の配列になり、各要素である配列は順に、棒0からの各音の設定を保存しています。
この配列要素内に保存される音は16bitのバイナリデータになります。下位ビットから説明します。
- 0-6
- MIDIのキーの値です。マリオシーケンサのWAV音もMIDIのキー値として表現されていることが元のマリオシーケンサとは異なります。MIDIのキー値は1オクターブを12の音で表現し半音を含みますのでプログラムが半音であると認知すると♯で表記します。例えば61は楽譜上ではC#となります
- 7
- キーが♭であるか指定します。1の場合♭です。例えば61は通常はC#ですがこのビットが1である場合にはD♭と楽譜上では表記されます
- 8-12
- 音の種類を0から31で指定します。0から14はマリオシーケンサのWAV音であり、15から31がMIDIのチャンネル0から15になります。0はミク専用で、9はドラムマップ専用です。
- 13,14
- 音の長さを指定します。0は無限長、1は長さ0でありキーオフ、2は長さ0.5です。MIDI音にしか使用しません。
- 15
- 予約。現在は使用しておりませんが、音長を8種類までに増やすか、別用途に使用するかもしれません。
音以外の要素として文字列で"tempo=nnnn"という文字列が入るとプログラムが動的に再生テンポを変更します。この仕様は将来コマンドに変更するかもしれません。
複数のファイルを画面の楽譜にDrag & Dropすることで1つにまとめることができますが、この時各ファイルのテンポがこの仕様により保存され、再生時に曲中でテンポを変更することを可能にしています。
このため再生時にユーザがGUIでテンポを変えることは可能ですが、再生位置がこのデータを含む棒に来た時に自動でテンポが変更される(値によっては元に戻る)場合が存在します。
tempo
CurScore.tempoは曲のテンポをBPMで指定します。GUI上のスライダでは10から1000が指定可能ですがデバッグコンソールからこの値を再生中に変更することであり得ない速さでの再生を楽しむことができます。
機械にしかできない最高に楽しい悪戯です。:-)
end
CurScore.endには楽譜のエンドマークの位置を指定します。最終小節の次の小節の頭を通常は指定します。
loop
曲の再生時にループするか否かはこの値です。trueかfalseを指定します。
謝辞
全ての音楽データはニコニコ動画で有名なPhenixさんが公開されているデータを改変させて頂きました。ありがとうございました。
http://music.geocities.jp/msq_phenix/
走るミクさんのドット絵は「ドット絵描こうZ」さんからお借りしました。
http://blog.livedoor.jp/dotez/archives/cat_10020030.html
両方とも著作権は全て作者様にあります。
マリオシーケンサ自体も某社様のものなので京都に向かって深々と御礼申し上げます。
勝手なことしてすみません。訴えないで下さい。m(_ _)m
2014-05-26
マリオシーケンサをWebアプリにしてみた
(6月11日 加筆)
マリオシーケンサがChrome Experimentsに採用されました!
http://www.chromeexperiments.com/detail/mario-sequencer/
- 画面サイズの変更を可能に。左上のセレクタを使用して下さい。
- 赤い線の箱でガイドを表示
- マウス位置と音符が置かれる位置が微妙にズレていたのを修正
(5月29日、加筆修正)
現在、HTML5や携帯等のプログラマのお仕事を探しております。
よろしくお願いいたします。
ニコニコ動画で一世を風靡したマリオシーケンサを覚えていらっしゃる方は多いのではないでしょうか?
HTML5のCanvas、Web Audio API等を勉強するついでにWebアプリにしてみました。
こちらで遊べます。現在、手抜きでChromeでしか動きません。
http://minghai.github.io/MarioSequencer/
ソースはこちら。
https://github.com/minghai/MarioSequencer
リモートからのダウンロード時にPROMISEで待つように作り直しました。
Downloadを表示するspinner(くるくる回るやつ)が消えれば準備OKです。
本家のマリオシーケンサに比べ、音の3音制限が無く、シフトとコントロールのクリックで♯と♭の半音が使えます。
前バージョンに追加して消しゴムも実装しました。
Undoが実装されていないので下のほうの組み込みの曲を押すと入力中の曲が全て消えますのでご注意下さい。
画面下にダウンロードのボタンがありますが、これを押すと作曲中のデータを保存することができます。保存したデータはDrag & Dropで画面に入れると反映されます。
Drag & Dropには本Webアプリのデータだけでなく、本家のMario SequencerのデータファイルであるMSQファイルが使用可能です。(拡張子msq)
ニコニコ動画でMario Sequencerでの大作をいくつも作られたPhenixさんがそのデータの一部を公開して下さっています。
http://music.geocities.jp/msq_phenix/
ここからデータを落として展開し、全て選択してドラッグアンドドロップすることで連続して聞くことが可能です。
ただし、一部のファイルには番号が1.5.5.5.5のように付いているものがありますが、これらは
通常の小数1.5555になるように直して下さい。また番号の付いていないファイルなどは連番を付ける必要があります。
複数ファイルを接続する場合に、異なるテンポの曲を繋げると両方のテンポを記憶し、曲の途中でテンポを変更することができます。
複数ファイルを接続することで24小節制限が無くなり、理論的にはほぼ無制限の長さの曲が作曲できます。
MSQもJSONもDrag and Dropを行うと1つのファイルに接続することが可能です。
Phenix氏が作成された組曲:ニコニコ動画を試しに上げてみました。
http://minghai.github.io/MarioSequencer/?url=NikoNiko_suite.json&auto=true
URLにCGIのGETの要領でオプションを指定することができます。
作成されたファイルをどこかにアップロードし、URLで指定すれば好きなファイルを外部からロードできます。auto=true(またはa=t)を付けることでロード後に即演奏を開始します。
以上、楽しんで下さい。
ここから下は開発者以外、読む必要がありません。
HTML5上でのゲーム開発について
HTML5上でのゲームの開発はCanvasに描画して、requestAnimationFrameで回すというのが王道かと思います。正直、ゲーム開発には低レベル過ぎてあまり効率の良いものではない気がします。
既にHTML5上でゲームを開発するフレームワークがいくつも存在するので、そういったものを利用したほうが良いのかもしれません。今回は使用していません。
JavaScriptのパフォーマンスはかなり良く開発初期には音楽という特性に全く間に合わないのではと考えていたのですが、自分の一世代古いCorei7のマシンでもBPM1500くらいが余裕で回せました。しかし、2008年のMacBookで実行した所かなり重く感じました。ChromeのMac OS版ではなぜか2008年のMacBookにてGPUを使用することができないのでCPUがぶん回ります。GPUによる二次元レンダリングのハードウェアアクセラレートが使用できないと重いようです。
開発で一番残念だったのはやはりブラウザ間の差異です。PREFIXが相変わらず必要なだけでなく、疑似要素、pseudo elementの名前等には各ブラウザで全く統一性が感じられません。
今回はChromeだけ対応にしてしまいましたが、ある程度完成したらFirefoxだけには対応したいと考えています。
今回、Web Audio APIを使用しましたが、かなり使いやすかったです。こちらでO'reillyの本が全文公開されています。
http://chimera.labs.oreilly.com/books/1234000001552
今回のアプリでは各音の種類にはFの音しか用意されていなく、playbackRateを操作することで音程を操作しています。この課程で本家には無かった半音の演奏も可能になっています。
残念だったのはcreateBufferSourceで作成したノードにはdetuneが無いことです。音程の操作をかなり簡単にするメソッドなのですが、どうも自ら作成した音のソースにしか無いようです
http://chimera.labs.oreilly.com/books/1234000001552/ch04.html#s04_2
Web Audio APIの再生はいくらでも重ねることができるのですが、マリオシーケンサは同じ音が続くと音がキャンセルされます。この部分をわざわざ実装しなければならないのが大変でした。
マリオシーケンサの音のキャンセルルールが明文化されていないので適当に実装してあります。このような細かな部分が元祖から本家に至るまで細かく異なるようです。(それを言えば元祖は音色によっては複数のサンプリングを異なる音程に用意しているようですが).
再生の音の重ね合わせが多いとひずみが発生します。これを抑えるためにcompressorが入れてあったのですが、compressorを入れるとプチプチノイズが目立つようになり取ってしまいました。
prototype.playChordにコメントアウトして残っていますのでコンプレッサが欲しい人はそこをいじって下さい。ローパスフィルタを入れようかと思ったのですが時間が足りずに入れていません。
マリオによる音楽の再生はrequestAnimationFrameが60FPSであるという前提を利用しています。しかしベストエフォートであるこのAPIは測ってみても5msかそれ以上は振れがあるようです。最初は演奏開始時から経過時間を測定し、綿密に演奏するアルゴリズムにしていたのですが、それだと再生中にテンポを変えることができず面白くありませんでした。現在は現在位置と現在のテンポの値から簡易的に音を鳴らすタイミングを量るようにしています。結構いい加減なのですが、安定して再生できています。
60FPSで再生するなら理論的には3600BPMまでは行けそうな気がしたのですが、実際には2000BPM近くから音の予約と実際の再生の間のラグが大きくなっているような気がします。画面と音との同期が崩れてしまいました。Chromeの開発者コンソールを開いて再生中に以下の要領でGUIでは設定不可能なテンポを設定することができます。
curScore.tempo = 2000
今回、初めてDrag & DropのAPIを使ってみましたが、余計な権限もいらず簡単でとても良いですね。
またPromiseも多用してみました。
Promiseは複数ファイルを並列にダウンロードしつつ、ファイルを番号順に処理するのを並列に行うという技をこちらで紹介していたので参考にさせて頂きました。
http://www.html5rocks.com/en/tutorials/es6/promises/
この記事は余計なことも多く書いてあって長いのが難点ですが、色々なケースに対応する手段がサンプルが豊富に紹介されていてとてもお勧めです。
今後の予定
やりたいネタは数多くあるのですが、勉強しなければいけないことも多過ぎて困ったものです。
とりあえずイメージと音は除いて、コードは一切の権利を主張しませんので皆でフォークして拡張し下さると嬉しいです。
2014-04-13
非公式PDF版SICPのKindle版を公開しました
先日、公開した非公式日本語版のSICPですが、想像を越えた範囲から好評を頂きました。
本当にありがとうございます。
Kindle版を欲しいという方が複数見えましたのでとり急ぎですが作っておきました。
Kindle PaperWhiteに最適化してあります。
https://github.com/minghai/sicp-pdf
通常版もかなり細かな修正が多数入っておりますので改めて、再ダウンロード願います。
修正内容については各texファイルのコミットログを御覧下さい。
Kindle版の作り方ですが、
- jsicp.texの頭にある、geometryパッケージのオプションをいじってKindleのスクリーンサイズに合わせる
- \newenvironmentに記述のあるテキストの各部分の大きさを調整
- \figureのPDFの幅を合わせる
- 色を単色に戻す
- どうしてもはみ出す部分を個別対応する
最終的にはみ出す部分の調整の作業量が膨大ですが、難易度は低いので他の電子書籍リーダー向けに組版し直すことも簡単に行えるかと思います。
見落とし等あるかもしれませんが、その場合この記事のコメントにてお知らせ下さい。
頂いたご意見について
色々な方に見て頂けたお陰で厳しい御意見も数多く頂きました。
全てごもっともなご意見です。
反省して次に生かしたいと思います。
ありがとうございました。
奥村先生に頂いたご意見でWindowsでなくともTeX環境について変わらないというお話がありましたが、昨年8月時点でTex Live 2013がデフォルト設定でインストールできるLinuxディストリビューションがリリース前のUbuntuのRC版しか無かったことが1つ念頭にありました。私自身がyumやaptのレベルでしか行いたくなかったこともあります。また、その後xelatexへの環境移行について調べている時に、各パッケージ作者様の記事でWindows版ならスタイルファイルがデフォルトでインストールされていることなどが触れられており、あのような表現となりました。実際に、検索して探している時点でもWindowsの情報が一番多かったと感じました。
Mac版にも素晴しいインストーラが提供されているようですが、私の環境ではMacに空きHDDが全く無かったので試していませんでした。恐らくMacの人は日本語では苦労しないかもしれません。
数学のレベルですが、一般の情報教科書に比べて難しくないとのご意見も頂きました。また学生の一部の方に脅しが効き過ぎてしまい申し訳なかった部分もありました。普通の理系の大学に受かる方ならあまり問題にならないかと思いますが、こればかりは個人差も大きいので難しい所です。写真付きで指摘されていたのが電子回路の微分方程式の部分ですが、あそこは積分近似でdeltaを足しているだけなことに気付けばそんなに難しくないかと思います。実際、課題3.78はわからなければ無視してもその後に影響はありません。
少々、難しいのが高校の情報で二進数を習うと浮動小数点表現等習っているかと思うのですが、その辺りをきちんと理解していないと数値解析による近似値演算の課題の意味がわからないかと思います。近似の収束の加速当たりはわからなくてもあまり問題は無いですが、近似値を求める課程は理解していないと、パラダイムを変えた所で、繰り返し出てくるので問題になります。
翻訳の品質についてもご指摘を頂いております。先の記事ではpull requestを求めましたが、この記事に対するコメントでも全然かまいません。ユーザ登録無しでもコメントはできますので、間違いのご指摘から、ここが日本語になっていない、意味がわからない等の指摘のみでもかまいませんのでコメントを下さい。
何のお礼もできませんが、校正にご協力頂けた方のお名前はPDFの中でもご紹介していきます。
今までに2名の方からpull requestを頂き、全て反映しました。本当にありがとうございました。
私自身も時間ができ次第、再び校正を開始する予定でおります。
PDF版の品質の向上にはまだ時間がかかるかと思いますが、皆様のご協力をぜひよろしくお願いいたします。
数式中の英語について、xelatex環境で日本語が出ないため翻訳していなかったのですが、\msgboxで回避できることがわかりました。今後、数式の中の英語も翻訳していこうと思います。
IPAフォントに等幅が無いため、等幅を前提に書かれた部分にズレが生じてしまっています。この点について何か良いアイデアをお持ちの方がありましたらコメント欄にてお知らせ願います。
最後にid:yoshiko_pg さんの以下の記事を拝見してとても嬉しかったです。
数学・情報系を専攻してないWebエンジニアがSICPを読んだメモ (1.1)
実際に読んで下さった方がいたことがとても励みになりました。
先週、偶然にもまたHackerNewsにSICPの紹介記事が掲載され、海外でもまたSICPが盛り上がっています。
http://hackerretreat.com/why-how-start-sicp/
この記事はとても長いですが、各界の有名ハッカーのSICPへの言及等も紹介されておりとても面白いです。
私としても別に私のPDF版でなくとも、一人でも多くの人が原文や和田先生の訳を通じてSICPを読んで下さればと思います。そしてSICPについて語り合い、その世界を広げて行くことができれば本望です。
2014-04-02
非公式PDF版SICPの全訳を公開しました
また1年振りの更新となりかけました。
Andres Raba氏により2011年から開発が続けられている、非公式PDF版SICPを全訳しました。
ファイル
恒例のgithubです。
https://github.com/minghai/sicp-pdf
jsicp.pdfが日本語版の本体です。
ejsicp.pdfはデバッグ用の日本語・英語併記となります。
ライセンスはCC BY-NC-SA 3.0です。商業使用は認められないことにご注意下さい。
SICPとは何か?
SICPとはMITが作成した何も知らない新入生向けのプログラミングの教科書です。
プログラミングと強調したことには理由があります。この本は良くあるプログラミング言語の教科書ではなく、あくまでもプログラミングを勉強するための教科書だからです。このことはこの本の中でも、最初の前書き、序文にて何度でも繰り返し強調されています。筆者達がこの本をそれまでの教科書から著しく際立たせる特徴として誇る理由です。
米国の新聞、ボストングローブ紙のMITの創立150周年記念企画にて作成されたMITでの最も重要な発明リストにもこのSICPは選ばれています。
Harold Abelson and Gerald Jay Sussman, a pair of MIT computer science professors, wrote “Structure and Interpretation of Computer Programs,” which remains a classic for encouraging the teaching of not one specific programming language, but big-picture themes students could apply across a range of programming scenarios.
MITの計算機科学の二人の教授、Harold AbelsonとGerald Jay Sussmanは"SICP"を出版しました。 これは1つの特定のプログラミング言語を教えるのではなく、学生が一連のプログラミングの シナリオに渡って適用できる大局的なテーマを教えることを促す古典としてあり続けています。
より深い「なぜSICPが重要であるか」については以下のカリフォルニア大学バークリー校の
Brian Harvey氏による以下の記事に説明されています。
Why Structure and Interpretation of Computer Programs matters
この中で氏はSICPが革命的である3つの理由を挙げています。
1番が最も重要なことであり、かつ上でも述べられたことです。
2番はこの教科書の前書きや序文でも再三繰り返されている点です。SchemeとはLispと呼ばれるプログラミング言語のある方言です。大学の授業では実社会で人気のあるC言語やJava等を教えることが多いと言われています。しかし、SICPはLispを選択しました。その理由はLispがあまりにも簡単で、ほとんど教える必要の無い言語であるためです。この説明には実は嘘があり、本当にLispの標準仕様を全て理解することは実はとても大変です。Lispの標準規格であるCommon Lispの教科書は電話帳並の太さを誇ります。実はここに仕掛けがあるのですがSICPがプログラミングの教科書であり、プログラミング言語の教科書ではないという事実をもう一度思い出して下さい。SICPはLispの教科書ではないのです。従ってSICPではSchemeの極一部の機能しか教えません。しかし、それで十分なのです。これこそがLispの特徴であるのですが、Lispは世の中に存在する言語の中で最も文法が簡単な言語の1つです。LispはそもそもLIst Processorの略であり、リスト処理機という意味です。Lispでは全てのプログラムがリストと呼ばれる構造で記述され、プログラムとデータが区別されません。通常のプログラミング言語では言語の構文と文法、それにデータ構造を長々と覚えていかなければなりません。しかし、Lispではとりあえずの文法を覚えれば後はその流れで使うことができます。そしてこのLispの単純さはLisp自身をLispで扱うことの簡単さへと繋り、そのことがSICPというプログラミングの教科書に信じられない程の奥深さを与える布石となるのです。
3番はSICPという教科書の恐しさをとても良く表しています。SICPという教科書は信じられない程の幅広い内容を一気に扱います。例えば簡単に流れを追って見ると1章ではプログラミングの基礎とモデル、抽象化の意味を学び、2章までに渡ってプログラミングで利用される代表的なデータ構造とアルゴリズムを学びます。3章ではオブジェクト指向の元となる概念、状態とその変更について学び、並行プログラミングにて生じる問題について習い、従来の一方向なプログラミングとは異なる制約伝播システムについて習い、さらに時間により生じる問題を解決するために遅延評価とストリームの実装を習います。4章ではこれらの問題をより深く探求するために言語の評価機とインタプリタを開発し、独自のScheme実装として遅延評価を行うSchemeインタプリタの実装を始めとして、非決定性プログラム言語の開発、論理プログラム言語の開発へと進みます。そして5章ではプログラムの最もプリミティブな解釈の理解を目的として、計算機を自ら設計し、機械語を設計し、それを実行する評価機を実装し、そのためのSchemeコンパイラを実装します。さらにはSchemeインタプリタとコンパイル済みコードとの連携までを実装します。これだけのことを学部1年生の前期で行うと言ったら、普通の情報処理学科の学生であれば気絶するのではないでしょうか? :-) 実際には、MITですら5章全部を教えるのは不可能だと考え4章と5章の一部は外していると前書きにて説明しています。しかし、それでもSICPの教える内容は通常のものではありません。しかし、SICPはこれだけのことを教えるために、綿密に設計されています。1章から5章への流れは丁寧に積み上げられており、特に課題は同じ問題が違う形で、何度も丁寧に繰り返されます。学生はこの流れの中で、何が問題の本質であり、どのように解決されていくのかについて、計算機科学の歴史を追体験して行くことになります。
SICPの面白い点として他には、SICPが数多くのプログラミングパラダイムを一度に学べることが挙げられます。
この教科書は最初に置換モデルを学習し、その中の制約においてプログラムを行います。通常のプログラミング言語にて最も最初に習う、破壊的代入が最初に出てくるのはなんと3章です。そこで初めて、ここまで学生達が学んできたプログラミングパラダイムが関数型プログラミングであることを学ぶのです。3章ではオブジェクト指向プログラム言語に対する批判等も脚注に書かれ、盛り上がってきます。遅延評価においては課題を通して、プログラミング言語の設計において遅延評価の利用はプログラマに決定権を与えるべきであろうかという問題が読者に提起されます。3章の制約システムや4章の論理プログラミングを知っている人は日本のIT業界では割と少ないほうなのではないでしょうか。きっと楽しめると思います。
SICPは初心者向けの教科書です。しかし、中身はとても本格的な教科書になります。その範囲はとても広く、まさにこの本は計算機科学の入口の塊です。読者は常に脚注から計算機科学の歴史を学び、さらなる学習のための参考資料を知ることができます。PDF版の利点として参考文献には数多くのリンクが貼られていて直ぐに論文を読むことができます。恐らくですが、実際に情報処理学科を出た人達が読んでも学ぶことが多い入門書です。実際に私は情報工学科の出身ですが、それでもこの本からとても多くのことを学ぶことができました。
SICPの難点
SICPは新入生向けの教科書です。内容はとても簡単な所からスタートします。ところが難点としてSICPの内容は高校生までの数学と物理の電子回路の内容を"良く"理解していることを前提としています。
ぶっちゃけてしまえば、課題として出てくる数学や電子回路の話が結構難しいのです。
例えば微分、積分、素数、剰余、確率、極限、級数、行列の理解が必要となります。
ネットで検索すると結構SICPを始めて2章までに脱落してしまう人がいるように思います。
しかし、どうか諦めないで下さい。色々なレビューに書かれていますが、本当のお楽しみは3章以降だと思います。数学的な内容は意地でも頑張って理解して下さい。数学ガール等を先に読んでおくと内容の理解が進むかと思います。私は(株)ワークスアプリケーションズ様が主催して下さった「プログラマのための数学」勉強会の内容がSICPにて展開される数値解析の内容とほぼ重なりとても参考になりました。
http://nineties.github.io/math-seminar/
http://www.youtube.com/playlist?list=PLzJWjr7AvxH0YYpi2uAH_QHLaSJQ5fZrR
SICPの難点として、課題が非常に多い点も挙げられます。これらの課題は内容の理解にとても重要なため、全て行うことがお勧めなのですが、量が半端ではありません。そのため全てを行うことを自分に課してしまうとあまりに負荷が高くてやってられなくなります。どうせ後半にはオープンな課題として、これが答えられたら博士課程の価値がある等といった課題も出てきます。ですので、気楽にほどほどに行ってください。
ちなみに、検索すると世界中でSICPを勉強している人達の回答が見られますが、5章辺りになると皆、課題をやっていません :-)
最後に、SICPの重要なテーマに抽象化が存在するのですが、抽象化レベルの高い話は簡単に道に迷います。特に4章、5章ではプログラムが大きくなり、自分が何をやっているのか全くわからなくなります。しかも、最後の最後に至るまでプログラムが完成し、実行することがありません。これを克服するためにはさっさとSICPのサイトから完成したプログラムをダウンロードして、先に終わりを読んで実行してしまうことです。そしてプログラム全体を読みながら教科書を読むことで初めて全貌が掴めてくることでしょう。
SICPを読む前に
RacketはLisp処理系の一方言ですが、グラフィカルなIDEを持ち、複数の言語を使用することが可能で、その中にはSchemeやSICP専用の言語拡張が含まれます。特にSICP 2.2.4節で習うピクチャー言語は専用の処理系を必要とするので通常は実行することができませんが、Dr. RacketのSICP拡張を用いることで実際に実行することが可能になります。
http://www.neilvandyke.org/racket-sicp/
RacketとSICP拡張のインストール方法に関しては以下のサイトがスクリーンショットも豊富にまとめて下さっています。
http://www.applelife100.com/2013/04/02/programmin-environment-for-sicp/
Linuxを使用されている硬派な方にはMIT Schemeがお勧めです。教科書ではMITの実装と他の実装の違いが良く話題になりますので複数入れて比較してみるのも面白いでしょう。
http://www.gnu.org/software/mit-scheme/
どの選択を行っても、最初にデバッガの使用法について学んでおくことをお勧めします。
プログラミング入門者が最も最初に嵌るのが入力ミスであり、次にデバッグです。デバッガの使用法を知る人と知らない人とでは生産性に10倍以上の差がつきます。
非公式日本語版PDFについて
非公式日本語版PDFはAndres Raba氏による非公式PDF版の翻訳です。
https://github.com/sarabander/sicp-pdf
非公式PDF版には元となったLytha Ayth氏によるTexinfo版が存在します。
http://www.neilvandyke.org/sicp-texi/
非公式Texinfo版はMITによるSICPのオンライン上での全文公開を用いて作成されました。
元々、非公式PDF版は非公式Texinfo版に対してTeXの組版を挿入し、texi2pdfを行うことでPDF化するという戦略が取られていました。
しかし、残念なことにtexi2pdfが内部的に利用するpdfTeXは海外では主流なのですが、日本では独自にpTeXの開発が進んだために傍流でした。当然のごとく、texi2pdfでは日本語を表示することができませんでした。
その窮地を救って下さったのが以下のサイトでした。
http://moimoitei.blogspot.jp/2010/06/generate-pdf-with-bookmark-on.html
この記事が提供して下さったtexinfo.texを用いることで、無事にtexi2pdfの代わりにtexi2dviとdvipdfmxを併用することで日本語を出力することが可能になりました。しかし、LaTeXではなく、直接TeXを使うことが大きな障害でした。またこの記事も2010年のため、ASCIIやNTTのpTeXの違い等がコードには含まれており、現状には合っていない感じを受けておりました。私自身はSICPの勉強はしたかったのですが、TeXに時間を必要以上に取られることはストレスに感じておりました。この時点では翻訳のみを完成させた後に、MathjaxでWebに逃げる予定でいました。
その後、大きな転機となったのが、Andres Raba氏によるXeLaTeXの採用です。Raba氏はPerlによる力技でTexinfoをLaTeXに変換し、改めてLaTeXでの組版へと舵を切ったのでした。XeLaTeXはこれもまだ日本では傍流であり、滅多には使用されていません。しかし、幸いなことに以下のサイトにてXeLaTeXにて日本語を使用するためのパッケージを開発して下さった人がいらしたのです。
http://zrbabbler.sp.land.to/zxjatype.html
この2つの奇跡により、俄然とやる気がでてきました。実際には翻訳が完成してから、Raba氏提供によるPerlスクリプトにてLaTeX形式に変換し、日本語をきちんと表示するまでには語るも涙な苦労がとんでもなくあったのですが、割愛します。ただこの課程でtexinfoファイルとtexファイルの両方を同期させる苦労に耐えきれなくなったために現在、LaTeXファイルを直接変更しており、既にTexinfoファイルの内容は古いままになっております。現在においてinfoファイルをEmacsで閲覧したいという方は少ないと思いますが、もしご希望の方がいらしましたら御自身で反映してpatchを送ってくださるととても助かります。よろしくお願いいたします。
最終的には日本では最もTeX環境が進んでいるのは意外にもWindows環境であったために、LinuxからWindows環境へと移行しています。xelatexの実行はTeXWorksから行うことができたためとても捗りました。
非公式日本語PDF版ビルド環境を構築するためにはWindowsにW32TeXをインストールして下さい。あべのり様の作成して下さったTeXインストーラを使えば簡単に可能です。
http://www.math.sci.hokudai.ac.jp/~abenori/soft/abtexinst.html
フォントをダウンロードした後にフォントファイルを開くとインストールボタンが表示されますので、それを押せばインストールが完了します。明朝とゴシックの両方を必ずインストールして下さい。
後はTeXWorksでtexファイルを開いて黄緑色の再生ボタンを押せば勝手にコンパイルしてPDFを表示してくれます。
なお、この時にstyファイルが無いというエラーが最初は大量に出ると思いますが、どんなスタイルファイルが無いのかメモしてませんでした。すみませんが、検索して適当にインストールして下さい。
翻訳について
最初に、ど素人の翻訳なのであまり期待はしないで下さい。修正は大歓迎ですのでpullリクエストを下さい。
SICPの英語の大きな特徴は長文です。1つの文が5行や7行当たり前です。このことは教養の高い英語では当たり前のようです。しかし、これは翻訳においては問題になります。日本語と英語の語順の違いから、長い英語を逐語訳すると読めたものじゃなくなります。特に英語では頭から流れでどんどんと代名詞に置き換えられていくため、日本語にする場合に英語は終わりから訳すのだとかいうローカルルールを適用すると見事に破綻する場合があります。このため、原文では1文で書かれている長文をぶった切って短い文の集合にする場合が多くなりました。ただし、その分、原文の順をできるだけ守り、著者の意図を重視した流れに訳したつもりです。
SICPは新入生向けの教科書であり、入門書です。ですから、とにかく優しく訳したいと願いました。本文は全て「です、ます」に訳してあります。これは通常の教科書では珍しいかと思いましたが、少しでも読者の精神的な負担を減らしたいと考えました。
専門用語については可能な限り、検索しまくって正しいと思われる用語を適用しました。しかし、私に学が無い分、おかしな訳も混じっているかもしれません。ご指摘をお待ちしております。
最後に、法的問題を回避するために、私は和田先生が公開して下さった「公式な」翻訳を読んでおりません。そのため訳に違いがあるかと思います。その場合には、当たり前ですが、和田先生のほうを信用して下さい。日本を代表する先生と私のようなど素人では最初から勝負になりません。:-)
そもそも、2013年8月にピアソン桐原が撤退し、SICPが無くなると聞いたときにこれを訳せば喜ばれるのではないかと始めました。まさか後から和田先生が公式訳を公開するとは全く想像していませんでした。一時は本当に公開を止めようかと悩んでいたのですが明示的にオープンなライセンスで公開することには意義があるのではないかと考えました。ただ、何かあったらあっという間に消える程度の存在なのは確かです。
翻訳にも著作権が存在します。そのため、和田先生の公式訳を引っ張ってきて、こちらの非公式訳に入れるような修正は行わないで下さい。何卒、よろしくお願いいたします。
お助け下さい。その1
現状のPDFは読めば読む程、細かなミスに気付く状態です。ぜひ、誤りをご報告下さい。
また現状のPDFは日本語の禁則処理等が破綻しており、まだまだ問題が存在します。TeXnicianな方々の助けをぜひ頂きたいです。
よろしくお願いいたします。
お助け下さい。その2
現在、転職先を探しています。インフラ系の知識もありますが、基本的にはプログラマの仕事を探しています。過去の記事を参照して頂けますとわかりますとおり、Web系の開発や携帯の開発等を仕事と趣味の両面にて行ってきました。HTML5方面もあまり深くはありませんが、手広く勉強しており、過去にはCoffeeScript本の翻訳等も行っています。
何か良い話がございましたらnarumi ドット katoh アットマーク gmail ドット com までメールを下さい。
よろしくお願いいたします。
2013-05-15
[翻訳] CAP定理 FAQ
Cloudera社のHenry Robinsonさんが書かれたCAP定理のFAQを翻訳しました。
https://github.com/minghai/cap-faq/tree/ja_JP
GitとGitHubの知識が全然足りなくて苦悩する毎日....
Consistency等の用語は全て英語のままにしてあります。
誤訳等ありましたらぜひお知らせ下さい。