【 Making「音声出力」その2 】 |
---|
Home | PC-6001mkII | Program | etc |
このページでは、音声出力のながら処理研究の過程を書いています。 |
2010/05/xx:解析その3 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ここまで来たら、音声を鳴らしながら他の処理もしたいところだ。 SRでは、この芸当が出来るらしい。話によると、音声出力専用(?)の割り込みがあるとの事。残念ながら、mkIIではそんな割り込みはな...まてよ通常の割り込みならあるな。 これをうまい具合に利用すれば音声出力の「ながら処理」が出来ないだろうか? そもそも、なぜmkIIでは音声出力時にほぼ割り込みを止めているのだろうか?憶測ではあるが、音声合成ROMからのステータスを受け取るタイミングがそれだけシビアなのだろう。 という事で、以下のような簡単なプログラムをmkII実機で実行し、各段階のステータスの変化(ポートE0Hからの入力の変化)を見る。
おさらいをすると、ポートへの出力は、E2H → E3H → E0H → E0H ...(以下7バイト or 1バイトのグループでポートE0Hへの出力が続く) の順となる。 まずはポートE2Hまで出力して試してみる。...ステータスは[00H]のまま変化なし。あれ、考え方を外したかな?まあいいや次! 次は、ポートE3Hへの出力後の状態を見る。結果は、最初の30回ほどが[A0H]、そこから先が[E0H]となった。ただ、マシン語処理の終了後にBASICから「?INP(&hE0)」で確かめると48、すなわち[30H]が帰ってきた。どうやら、少なくとも[A0H][E0H][30H]の3段階に変化しているようだ。 前の結果と照らし合わせると、値の意味合いはこんな感じだろうか?
ウェイトのループ回数を5回にして何度か試すと、こんな感じになった。
1〜6バイトでは、[E0H]は概ね50〜70程度なのだが、たまに12〜28となる。 7バイトデータの区切りでは、[A0H]の時間が長くなる。この時、[A0H][E0H]の値にかなりのムラがあるが、[A0H]と[E0H]を足した数は割と安定している。 測定の方法や測定に使用する音声データで大きく変わる可能性もあるが、とりあえずこの結果を参考に処理を考えることにしよう。 |
2010/06/xx:割り込み処理その1 | |||||||||||||||||||||||||||
さて、割込み処理について考える。 前の結果から、7バイト単位の区切りでは受付可能状態(ステータスがE0H)が最短で45カウント分とわかる。つまり、これ以上時間が空くと音声出力に失敗する可能性があるという事だ。 さて、この45カウント分とは、いったいどれくらいの時間なのか?計算してみよう。
えーと、つまり... 8 + (29 + 85 + 19) * 45 = 5993ステップ。 CPUがおおよそ2MHzとすると、1ステートは0.0005ms。 という事で、5993 * 0.0005 ≒ 3.0ms 一方、mkIIの通常の割り込み処理間隔はマニュアルより2/975秒という事で、約2.05ms。一応3.0msには収まっているが、何らかの原因で割り込みが飛ばされるとアウトだ。 という事で、割り込み回数を倍に増やす事にする。これなら、割込み処理が1回飛ばされてもなんとかやってくれるだろう。 |
2010/06/xx:割り込み処理その2 | |||||||||||||||||||||||||||
さて、マシン語の処理を作っていくか。 マシン語のプログラム構成は、以下の3種類で行くことにする。
ステータスは、USR()関数から別の音声出力要求があったら現在の音声出力を中断できるようにしたいので、こんな所かな?
初期化処理ではステータスを0にする。 USR()処理では、ステータス0なら255に変更、それ以外はステータス変更なしで次の音声データの番地を控えておく。 とまあ、こんな所だろうか。 |
2010/06/30:ながら音声 V1.0 |
ここまで出来れば、あともう少し。 サンプルの音声データを用意し、マシン語を呼び出すBASICプログラムを作成する。カーソルキーの上下左右で4種類の音声を出力するようにしようかな? お手軽に、マシン語プログラムと音声データを読み込むようにしてっと、こんな所かな。いざ実行! PC-6001VW上では、概ねうまく動いていた。ただ、なぜか音声が少し遅く再生される。また、画面をスクロールするとたまに音声出力がされなくなる問題が残る。 実機でも試してみるか。簡易的にテープ用のイメージを作成して、mkII実機にロードする。いざ実行! ...あれ?何も鳴らない。暴走しているわけでもなさそうだ。うーん、なんだろう。 デバック用に途中経過を出力してみると、はじめから3〜4バイトの出力まではうまく動いているようだ。やっぱりエミュよりもタイミングがシビアなのかな。 結局、実機ではうまく音声出力がされないまま、ながら音声を公開した。 まあ、最初にやろうと思っていた事は達成したので、ここまでにするか。 と、この時は思っていた。 |
2011/01/09:改善 |
前回の公開から5ヶ月ちょっと経った頃、突如改善を思い立つ。 前回は割込み毎に1バイトずつ出力していたのだが、1割込みで7バイトを一気に出力するように変更する。 という文章を書いて思ったが、せっかく、前に 7バイトデータの区切りで時間的余裕が大きい事がわかったのになぜ前回は1割り込み1バイト出力にしたんだろう...? はじめは、PC-6001VWで確認...特に問題なさそうだ。前回よりもスムーズにしゃべるようになった気がする。 さて、次はmkII実機だ...おぉ、しゃべった。 これで成功したと思ったのもつかの間、なぜか実機では続けて2回目の音声出力がされない。調べてみると、初回の音声出力後の内部ステータスがエミュと実機で異なっていた。 違いの元を辿ると、音声出力後のポートE0Hの出力結果がエミュと実機で以下のように異なっていた。 任意語の音声出力(TALK "F2 A." 等)を実行した後のポートE0Hの出力 エミュ:00H、実機:30H 固定語の音声出力(TALK "F21." 等)を実行した後のポートE0Hの出力 エミュ:00H、実機:00H エラーになると音声出力処理を飛ばしているので実機ではうまく動かないことがわかったが、そもそもなぜ実機ではエラーになるんだろう? 固定語出力と任意語出力の処理の違いがわかれば音声出力の真の終了条件もわかるのだろうが、固定語出力の処理を追うスキルはない。ならば別の手段で回避すべきだろう。 まず、ポートE0Hの状態にかかわらず音声データの終わりまで来たら内部ステータスを00Hに戻すように変更した。あともう一つ、7バイトデータ出力前のポートE0Hのエラーチェックを外した。エラーチェックは7バイトデータ出力のループ内でも行っているので、大きな問題は出ないだろう、多分。 エミュで動作を確認後、実機での動作を試みる。 ...いけてる、かな?うまくいってそうだ。 こうして、V1.1が完成した。 |
← その1 | Making「音声出力」 | その3 → |