tsutsuiの作業記録置き場

NetBSDとかPC-6001とかの作業記録のうち、Twitterの140字では収まらない内容や記事としてまとめるべき内容をとりあえず置いてみる予定

「Tinyみずいろ"Prologue" for PC-6001(32k)」を実機で動かすまで(2)

前回の続きで、Tinyみずいろの配布 wma をどう処置したか、についてです。

P6DatRec

P6界隈でテープ音→バイナリ変換といえば P6DatRec です。P6DatRec は入力として 8ビットモノラルの wav ファイルが必要なので、とりあえず wma を何かしらのツールを使って 8ビットモノラルの wav に変換してやる必要があります。

Tinyみずいろ実行トライをしていたときは「とりあえずやってみる」ということで適当に検索して Rip!AudiCO FREE を使って wav に変換したのですが、 Rip!AudiCO FREE には 8ビットの wav 出力の選択肢はないようでした。ツールを探すことに時間を割くのは本題ではなかったので「変換した 16ビットの wav をさらに NetBSD 上で sox を使って 8ビットの wav に再変換する」というとりあえずの手段を使ったのですが、今から変換するのであれば別のツールを使ったほうがお手軽です (詳しくは別エントリで)。

こうして変換した wav を P6DatRec にかけて PC-6001V のエミュレータで CLOAD してみると、まったく読んでくれません。最初のファイル名すらダメ。変換後のファイルを見てみるとこんな感じです。


ちなみに正しい (はずの) データは以下のように BASIC プログラムヘッダから始まります。


正しいデータと並べてみると「なんとなくそれっぽい痕跡はある」というのはわかりますが、補正とか修復とかいうレベルからは程遠いという感じです。

wma波形

wma から変換した wav を WaveSpectra で見てみるとこんな感じです。


これはロングヘッダの先頭の 1バイトの D3h の部分です。とりあえず正しいデータがわかっている前提で目視するとなんとなく 1200Hz (0) と 2400Hz (1) はわかりますし、実際この最初の1バイトについては P6DatRec でもデコードできています。ただ、波形が歪んでいるだけではなく 3倍高調波くらいの細かいサイン波が重なっているところが問題で、これが電圧0付近に現れると波形のゼロクロス位置でエッジ検出している場合に誤検出する原因になります。

P6DatRecのデコード方法

P6DatRec の README.TXT の記述では、 0/1 判定は以下のように記載されています。

(前略) 無音の位置から負の方向に波形データが横切るときを開始点として、 1200Hz の波1個ぶんをフーリエ変換します。その値が敷居値以上になったら、0とみなし、そうでないなら、1とみなします。つまり、1200Hz の正弦波でも 2400Hz の正弦波でもないものはバイト中では1とみなされます。

上記はスタートビット検出後の 1バイト (8ビット) 中の検出ですが、要は「波形がゼロクロスしてから1ビット分の時間中に周波数成分として 1200Hz が含まれるかどうか」で判定しているようです。スタートビット開始判定時の計測については明確に書かれていませんが、変換時の *.rep のログ出力の pos の位置データからすると

  • 波形がゼロクロスしてから1ビット時間分フーリエ変換
  • 変換中の1ビット時間経過前に再度ゼロクロスした場合、かつその前のビットでスタートビット検出をしなかった場合はオーバーラップしてフーリエ変換

ということをしているように見えます。

この場合、前項で書いたようにゼロクロス付近で高調波が暴れるような波形だった場合にはデコードが失敗する確率が高くなるはずで、実際の挙動とも合致していると思われます。

P6DatRecのエンコード方法

話は少し脱線しますが、 P6DatRec の P6テープバイナリ→wav変換についても少し調べてみました。

Tinyみずいろの BASICのバイナリは t2b というファイル名から推測されるように txt2bas で BASICリストテキスト→P6テープバイナリ変換をしていると思われます。P6テープバイナリから音声データへの変換がどう行われたのかを知るすべは (作者の方にお聞きしない限りは) ありませんが、Tinyみずいろの公開時期から考えると P6DatRec が使用されたものと思われます (P6DatRec の最新版(?)の公開日は 1999年1月とのこと)。

P6DatRecの README.TXT の「音量比」の項には以下の記述があり、出力される wav はサイン波のようです。

「音量比」生の波形データを見る限り、 1200Hz の波と 2400Hz の波の振幅に差があるように思いましたので、その日を設定で与えるようにしています。デフォルトは 1.32 ですが、これも作者の勝手な判断です。

実際に P6DatRec が出力する wav の波形を見てみると以下のような感じです。

形としてはサイン波ではありますが、 2400Hz の音に対してサンプリングが 11025Hz 8ビットなので結構苦しい感じがします。このギザギザが wma 圧縮されるとさらに難しいことになったということかも? (ちなみに配布の wma は 44.1kHz サンプリング)

P6実機のCMT出力波形は確認していませんが、 TinyProjectさんのPC-Techknow6000 Vol.2 <回路図篇> の回路図を見ると、サブCPUのポート出力つまり H/L 2値出力から RC のローパスフィルタ経由で出力されています。この場合、波形的には矩形波にはならずなまり気味のサイン波に近い波形、かつフィルタのカットオフ周波数に近い 2400Hz のほうが振幅が小さくなるということにはなると思います。

一方、TINY野郎さん作の なんでもピーガー では wav 出力波形は完全な矩形波です。


P6実機的にどちらが良いのかというと、入力I/F回路的には「H/L しきい値判定した上でエッジ検出」ということになると思うので「極端に歪まない限りどっちでも同じ」とは言えると思います。が、データの復元に苦労した身からすると、 wma 圧縮的にはどちらのほうが元波形の再現度が高かったのだろうか、などとどうでもいいことを考えるのでした……。

波形整形

と、ここまでいろいろと調べたようなことを書きましたが、これらは実はこのエントリを書くにあたって改めて調べたことで、実際に Tinyみずいろトライをしていたときは事前にデータレコーダー用波形整形ツールの情報を聞いていたのでそれを試しただけだったりします。

もともとはデータレコーダーの修理が難航していたときに「データレコーダー実機が有効なのは REMOTE 端子による START/STOP 制御だけだから、ラズパイかなんかでデータレコーダーの模擬みたいなことできないんかな」というツイートに対して、「AVR で SD の wav ファイルをデータレコーダーとして再生するものを作っている人がいる」と教えていただいたものです。

具体的には、上のツイートで教えていただいたブログの次のエントリ データレコーダーのエミュレータを作ってみた (その5) に wav 出力波形検証という形で紹介されている、「OUT of STANDARD」さんの「PC-8001のページ」の「cmt8001」および「pcm8001」が使用したツールです。
2019/6/22追記: geocities からの移転に伴いバイナリ配布が一時停止中のようです

PC-8001+PCG8100 で遊んでるヤツが まだ いるぞ というのが同志という感じです(笑)


なお、上記の データレコーダーのエミュレータを作ってみた (その5) のエントリでは各社のデータレコーダーの波形出力についても調査されていて、「データレコーダーはテープの波形を矩形波に整形して出力している」というのも注目点です。

cmt8001

ここから先は Tinyみずいろ実行トライをした当初の試行錯誤の話なので、今からやるならもっと効率の良かった方法もあったりするのですが、記録用ブログということで当時を思い出しながら順に書いていきます。

cmt8001 の使い方は基本的には上記ブログエントリおよび付属の readme.txt にあるとおりなのですが、 readme.txt の内容が若干古いままになっているようであること、また、元が PC-8001 用である (= デフォルトのボーレートが 600bps である) ことなどから動作させるのにちょっととまどったところもあるのでそのへんをメモっておきます。

動作環境

readme.txt の「■動作環境■」項には

・Java2SE 1.3.0〜 (JDK または JRE 1.3.0〜)
JDK または JRE は、別途入手してください
> JDK J2SE1.3 http://java.sun.com/j2se/1.3/ja/index.html
> JRE J2SE1.3 http://java.sun.com/j2se/1.3/ja/jre/index.html

などとあり、 sun という文字列に「お、おぅ」という気持ちになったりするのですが、普通に 現時点最新の Java SE8 で動作するようです。Windows 10 Pro 64bit および Windows 10 Home 32bit それぞれで問題なく動作しました。 NetBSDLinux でも Java さえ動けば動くのだと思いますが試していません。

起動方法

readme.txt には Windows での起動について

Windowsの場合、cmt8001.jar をダブルクリックしても起動できますが、
 その場合はコンソールが開きません(=訳がわからなくなる)のでお勧めしません

とあるのですが、コマンドプロンプトから cmt8001.jar を実行しても特にコンソールの出力はダブルクリック時と動作は変わりませんでした。「清く正しく Java的コンソールから起動する方法」があったりするのかもしれませんが、いずれにせよログ出力は *.log および *.fsk の各ログファイルに出てくるので、よほど細かい解析をする場合以外はダブルクリック起動で問題ないと思います。

変換オプション

readme.txt にはコマンドラインを指定するコンソールモードの使用法だけが載っており、ダブルクリック起動時の GUI の説明が無いというストイック仕様でこれまた戸惑うのですが、基本的には前述のブログ通りで以下の画面設定にすればOKでした。
これ以外にもいろいろ試したのですが、Preamplifier が元の wav ファイルの音量によっては ON/OFF で多少データに変化があったものの、それ以外のオプションについては上記以外の設定では変換途中でエラーになる場合がほとんどでした。


「Wav2Fsk」のオプションは readme.txt 記載のコマンドラインオプションと以下のように対応します。

GUIアイコン CUIオプション 動作
Preamplifier -amp プリアンプで音量を補強する
Low Pass Filter -lpf=0,1,2 ノイズ除去 (0:なし/1:普通/2:強)
High Pass Filter -hpf 基線を補正する
Wave Phase -phase=0,1,2 0:位相モード(1) / 1:位相モード(2) / 2:「半波長」モード
BLANK Level -low 無音判定レベルを半分にする


Preamplifier, High Pass Filter のアイコンは OFF時が黒、ON時が赤。
BLANK Leve のアイコンは 通常時が白、「無音判定レベル半分」の指定時が赤。
Low Pass Filter, Wave Phase はパラメータの 0,1,2 がアイコンの 黒/青/赤 に対応。

各オプションの詳細については readme.txt の「■オプションの詳細■」項を参照してください。

各オプションの意味を理解した状態であればそれぞれのアイコン形状で指定している内容は直感的にわかるのですが、各種パラメータの組み合わせをトライ&エラーする場合は Low Pass Filter と Wave Phase が3種類のトグルであることに注意する必要があります。最初気づいてなくてハマりました……

「Fsk2Cmt」のオプションは見たままですが、以下のとおり指定します。

  • ボーレートは「1200 baud (-x2:2400)」を明示的にチェック。(起動時のデフォルトは 600 baud)
  • 「Parity Bit」のチェックは外したまま
  • 右上欄外の「2400/4800Hz」のチェックも外したまま

PC-8001/8801 の場合は CMTのシリアル信号がシリアルチップの uPD8251 につながっているようなのでパリティチェックに意味がある場合もあるのでしょうが、CMT がサブCPUで処理される PC-6001 の場合はパリティを使用するものは無いと思います。また、 2400/4800Hz のオプションは MSX の 2400baud 用と思われます。

wav2wav変換

readme.txt のコマンドラインオプションにある -w2w の「Wav2Wav変換(補正のみ)」は GUIメニューから行えます。


元の波形を tiny_mizuiro_prologue.wav で読み込んでいた場合は tiny_mizuiro_prologue.mod.wav が補正後の波形として出力されます。整形前後の波形を比べてみると違いは一目瞭然です。

整形前:


整形後:


が、 Tinyみずいろの wma ファイルの場合、この wav2wav 変換で補正した wav を P6DatRec で変換した P6ファイルでもエミュレータでは BASICプログラムとして正常に読めませんでした。そのため、先のブログエントリでも解説されているとおり 「cmt8001」を利用してcmt形式にした後、「pcm8001」を利用してwavに戻す」 の手法を使いました。

実は wav2wav 変換でも設定次第でうまく読み込める場合があることが後からわかったのですが、それは別エントリで……

convert

cmt8001 を起動した後、変換対象の wav ファイルをドラッグアンドドロップし、「変換オプション」項で記載した設定にした上で「Convert」のボタンを押せば変換は完了です。

出力ファイルについては、 readme.txt に記載のあるとおり以下の4つのファイルが作られます。

  • foo.fsk
  • foo.log
  • foo.cas
  • foo.cmt

エラーで変換に失敗した場合は *.log の最後にエラーが記録されています。また、変換後の *.cas および *.cmt のサイズをエクスプローラー上で確認することでざっと変換が成功しているかチェックできます。パラメータを試行錯誤するときは参考にしてください。コンソールモードがあるんだから自動化スクリプトを組めよという話もある

readme.txt には *.cas と *.cmt の詳細について書かれていないのですが、 *.cas がメインのファイルで、 *.cmt についてはデータが BASIC 等の既知のフォーマットであった場合に生FSKビットデータの代わりに実データとして記録するファイルのようです。

pcm8001による再wav化

pcm8001 の動作環境については cmt8001 と同様に太古の Javaバージョン記載が残っていたりしますが、こちらも最新の Javaで問題なく動作するようです。

起動方法については readme.txt がさらにストイックになっていて「添付のバッチファイルを参照してください」などとありますが、普通に「pcm8001.jar をダブルクリック」で問題ないようです。

pcm8001 のウインドウが開いたら、先に cmt8001 で作成した「foo.cas」ファイルをドラッグアンドドロップします。 foo.cmt ファイルも開けてしまうのですが、前述の通り cmt8001 の出力としては foo.cas がメインのファイルで foo.cmt はそのサブファイル扱いなので注意。

casファイルをドラッグ・アンド・ドロップした後のウインドウは以下のような表示になります。


次にメニューの「Default」でボーレートを 1200baud に設定します。

メニューの「Configure」の項目については特に変更する必要はありません。

上記の設定の後、メニューの「File」→「Save As...」で開くダイアログで出力先の wav ファイルを指定すれば変換完了です。

動作確認

こうして pcm8001 で作成した wav ファイルをいきなり P6実機に投入してみると、とりあえず BASIC 部分はロードしてくれました。それがこのツイート。

内心 おおぅ と思いながら RUN してみると、ちゃんと後続の本体部分(?)のロードも始まりました。

が、うまくいったのはここまでで、ロードが完了しないまま wav ファイルの再生が終わってしまいました。

後からよく考えてみると、ロードが2回に分かれているのだから wav 化する場合も 2つの部分に分けてそれぞれにロングヘッダ (先頭のピー音) をつけなければいけない等々の問題があったのですが、とりあえずそのときは補正 wav を作るだけで力尽きていて、 BASIC 部分だけでも読めれば上出来というところでいったん打ち切ったのでした。まだエミュに慣れていなかったというのもあります

エミュレータでの確認

微妙に本末転倒ですが、 pcm8001 で作成した wav ファイルをさらに P6DatRec で P6テープファイルに変換すれば、PC6001V 他のエミュレータ上でも動作確認が可能です。 pcm8001が作成する wav の形式はストップビットが 2ビットということなのですが、 MSXはストップビットが 2ビットということもあり P6DatRec は問題なく変換してくれます。というかP6実機も問題なく読むみたいですね

エミュを起動して P6ファイルを突っ込んで CLOAD すると、実機同様 BASIC部分はちゃんとロードしてくれます。エミュキャプチャ画像はブログエントリ作成にあたっての再現映像です


そのまま RUN すると、実機同様のロード画面の後にちゃんとロードが完了して

PUSH ANY KEY が出てきました! おおぅ。ワクワク度が高まる一瞬です(笑)

ドキドキしながらスペースキーを押すと、Tinyみずいろのページで見た SCREEN 4 モノクロ背景色のフレームが出ました!


……が、「よっしゃ!!」と思ったのも一瞬で、すぐエラーで止まってしまいました orz


要は、補正しきれなかったというか完全に化けてしまっているデータがまだ残っていたということなのですが、今回も長くなってしまったのでデータ修正作業については次回に続きます。