演出機器を自動的に動作させるクリックとして使われるタイムコードについて書きたいと思います。
目次
本来は動画を扱うための物ですが、舞台やイベントの現場では機器の動作を同期させたり定時動作を自動化するための汎用制御信号として用います。規格名は「SMPTE12M」に定義される「LTC(Linear Time Code)」と呼ばれる物です。「SMPTE」とは「Society of Motion Pictures an Television Engineers(米国映画テレビ技術者協会)」のことであり、日本語では「エス・エム・ピー・ティー・イー」又は「シンプティ」と読みます。
規格の目的は動画のフレームのタイムアドレスを表す物です。動画は言わば超高速紙芝居ですが、何番目の画像かを時刻表現に近い形式で表します。ですから、演出器具を動かすためのクリックでもなければ、時刻を表すための物でもありません。性質上、その様に使えるだけです。
信号の電気的特性は、映像用の磁気テープでは音声トラックに書かれていたこともあり、一般的な音声信号とほぼ同等に扱うことが出来ます。
注意ですが、世間でタイムコードと呼ばれるシステムはこれだけではありません。動画に全く関係無いところで全く違うタイムコードが使われていることもあります。所構わず「タイムコードすなわちLTC」として話を進めると事故の基になります。
以下は、「SMPTEデジタル規格集3=TC,SDTIほか=(宇野潤三訳、兼六館出版、ISBN4-87462-045-0)」を参考にしています。
なお、LTCは地上波デジタルテレビ放送が始まる前の地上波アナログテレビ放送の時代に策定された物です。この記事はLTCについてですから、テレビ放送についての情報は地上波アナログテレビ放送を前提とした物になります。
「動画は超高速紙芝居」と書きましたが、動画は静止画を一定の間隔で差し替えることで動いているように見せる手法です。動画をスロー再生する(静止画を切り替える間隔を長くする)とカクカクと動きが飛び々々に見えると思いますが、静止画を切り替える間隔を一定以上に短くすると滑らかに動いている様に錯覚することが動画の原理です。
撮った動画を単に放映するだけなら不要なことかもしれませんが、動画の構成や編集が複雑になってきますと静止画単位で管理した方がよくなってきて、それぞれにナンバリングをする様になったのだと思います。
動画では静止画単位をフレームと呼びますが、それぞれに重複しないアドレス(ナンバー)を割付け、記録媒体にフレームの画像情報と並列に記録します。この様式が「タイムコード」であり、それぞれのフレームを表す物がタイムアドレスとなります。
タイムアドレスがあると便利ですが、最初のフレームから単に連番を付けるだけでは桁数が多くなって管理が簡単とは言えません。動画は時間に対して一定の動作をしますので「何分何秒目」と表した方が直感的にわかりやすいので時刻表現に近い形としたのだと思います。一般的には「何時:何分:何秒:何フレーム」と表します。最後の「何フレーム」は1秒の間のフレームの通し番号です。「0時0分0秒0フレーム」から始まり「23時59分59秒29(24,23)フレーム」までカウントできます。
そもそもが動画を静止画単位で管理するためのナンバリングですから、動画のフォーマットの基本を理解しておくべきです。
LTCを理解するためには次の二つが重要です。
1秒間に静止画が何枚あるか、という単位です。これが何種類もあります。単位表記は「fps」です。「フレーム・パー・セコンド( Frames par Second )」の略です。1秒間のフレーム数を表します。つまり、フレームレートとは何fpsであるか、という意味です。
主だったフレームレートは次の通りです。
【用語解説】NTSC(エヌティーエスシー)やPAL(パル)とはテレビ送信の規格。NTSCは主にアメリカ合衆国やカナダ、日本などで用いられ、PALは主にヨーロッパや旧ソビエト連邦圏で用いられています。
最も古く、現在でも基本となっているタイムコードの規格が「SMPTE12M」です。この中に「LTC (Linear Time Code)」が定義されています。
LTCはフレームと並列で保存される80bit長のデジタル符号です。規格の主な内容は80bitのデータフォーマット、変調方式、電気的特性です。規格から計算される物ですが、ビットレート(送信速度)も重要な情報です。
+4dB音声LINE信号に近似し互換性があります。
デジタル信号は0か1かの数値を表し、電気的には数値が0なら電圧が0v、数値が1なら電圧が規定値とするのが基本です。しかし、このまま長距離の送受信は出来ませんので、戻すことを前提に装置が送受信しやすい電気的な変更を加えます。これを「変調」と呼びます。
LTCではデジタル符号変調方式の一つである「差動バイフェーズ」を使います。
単線で表現します。クロックなどの制御信号線はありません。
単位時間内の電圧変化の回数で0か1を表現します。電圧値ではありません。
以下には「電圧が反転」とする文言がありますが、規定値プラスだった電圧が規定値マイナスへ、規定値マイナスだった電圧が規定値プラスに変化することを表しています。
文章ではイメージしにくいかもしれませんが、単位時間の始まりと終わりで必ず電圧が反転し、1の場合だけ単位時間の半分で電圧の反転が追加されます。
シリアルなデジタル信号ですから送信速度も大事な設定値です。
1フレームの送信時間と80bitの送信時間が等しいので、タイムコードのビットレートはフレームレートに比例します。
80bitのデジタル符号で表します。実際の順番はバラバラですが、大雑把に分類すると次の情報が記されます。
80bitの内訳は次の通りです。
データフォーマット表
ビット | 名 称 | 補 足 | ||
0 | フレームの 1の位 | 0bit目 | BCD表記 数値範囲0-9 | |
1 | 1bit目 | |||
2 | 2bit目 | |||
3 | 3bit目 | |||
4 | 第1 バイナリグループ | 使用しない場合=0 使用する場合は それぞれの設定値 | ||
5 | ||||
6 | ||||
7 | ||||
ビット | 名 称 | 補 足 | ||
8 | フレームの 10の位 | 0bit目 | BCD表記 数値範囲0-2 | |
9 | 1bit目 | |||
10 | NTSCモノクロ 30fps | 未定義 | 通常=0 | |
NTSCカラー 29.97fps | ドロップフレームフラグ | DF=1 / NDF=0 | ||
PAL 25fps | 未定義 | 通常=0 | ||
フィルム 24fps | 未定義 | 通常=0 | ||
11 | NTSCモノクロ 30fps | 未定義 | 通常=0 | |
NTSCカラー 29.97fps | カラーフレームフラグ | カラー=1 / モノクロ=0 | ||
PAL 25fps | カラーフレームフラグ | カラー=1 / モノクロ=0 | ||
フィルム 24fps | 未定義 | 通常=0 | ||
12 | 第2 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
13 | ||||
14 | ||||
15 | ||||
ビット | 名 称 | 補 足 | ||
16 | 秒の1の位 | 0bit目 | BCD表記 数値範囲0-9 | |
17 | 1bit目 | |||
18 | 2bit目 | |||
19 | 3bit目 | |||
20 | 第3 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
21 | ||||
22 | ||||
23 | ||||
ビット | 名 称 | 補 足 | ||
24 | 秒の10の位 | 0bit目 | BCD表記 数値範囲0-5 | |
25 | 1bit目 | |||
26 | 2bit目 | |||
27 | NTSCモノクロ 30fps | 極性補正フラグ | 計算により定義 | |
NTSCカラー 29.97fps | ||||
PAL 25fps | バイナリグループフラグ0 | 設定値は別表 | ||
フィルム 24fps | 極性補正フラグ | 計算により定義 | ||
28 | 第4 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
29 | ||||
30 | ||||
31 | ||||
ビット | 名 称 | 補 足 | ||
32 | 分の1の位 | 0bit目 | BCD表記 数値範囲0-9 | |
33 | 1bit目 | |||
34 | 2bit目 | |||
35 | 3bit目 | |||
36 | 第5 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
37 | ||||
38 | ||||
39 | ||||
ビット | 名 称 | 補 足 | ||
40 | 分の10の位 | 0bit目 | BCD表記 数値範囲0-5 | |
41 | 1bit目 | |||
42 | 2bit目 | |||
43 | NTSCモノクロ 30fps | バイナリグループフラグ0 | 設定値は別表 | |
NTSCカラー 29.97fps | ||||
PAL 25fps | バイナリグループフラグ2 | |||
フィルム 24fps | バイナリグループフラグ0 | |||
44 | 第6 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
45 | ||||
46 | ||||
47 | ||||
ビット | 名 称 | 補 足 | ||
48 | 時の1の位 | 0bit目 | BCD表記 数値範囲0-9 | |
49 | 1bit目 | |||
50 | 2bit目 | |||
51 | 3bit目 | |||
52 | 第7 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
53 | ||||
54 | ||||
55 | ||||
ビット | 名 称 | 補 足 | ||
56 | 時の10の位 | 0bit目 | BCD表記 数値範囲0-2 | |
57 | 1bit目 | |||
58 | NTSCモノクロ 30fps | バイナリグループフラグ1 | 設定値は別表 | |
NTSCカラー 29.97fps | ||||
PAL 25fps | ||||
フィルム 24fps | ||||
59 | NTSCモノクロ 30fps | バイナリグループフラグ2 | 設定値は別表 | |
NTSCカラー 29.97fps | ||||
PAL 25fps | 極性補正フラグ | 計算により定義 | ||
フィルム 24fps | バイナリグループフラグ2 | 設定値は別表 | ||
60 | 第8 バイナリグループ | 使用しない場合=0 使用する場合は モードによる設定値 | ||
61 | ||||
62 | ||||
63 | ||||
ビット | 名 称 | 補 足 | ||
64 | 同期ワード | 0bit目 | 固定値 | =0 |
65 | 1bit目 | =0 | ||
66 | 2bit目 | =1 | ||
67 | 3bit目 | =1 | ||
68 | 4bit目 | =1 | ||
69 | 5bit目 | =1 | ||
70 | 6bit目 | =1 | ||
71 | 7bit目 | =1 | ||
ビット | 名 称 | 補 足 | ||
72 | 同期ワード | 8bit目 | 固定値 | =1 |
73 | 9bit目 | =1 | ||
74 | 10bit目 | =1 | ||
75 | 11bit目 | =1 | ||
76 | 12bit目 | =1 | ||
77 | 13bit目 | =1 | ||
78 | 14bit目 | =0 | ||
79 | 15bit目 | =1 |
今はmicrochip社のPIC16マイコン以外にも安価で優秀なマイコンが数多くありますが、マイコンを使い始めた当初、私にも理解出来て安価に開発環境を整えられたマイコンがこれだったので今も愛用しています。当時はCコンパイラが大変高価だったため、その名残で未だにアセンブラで書いています。
PICマイコンは拡張ミッドレンジ16系を用います。上位機種に比べて処理能力や機能は劣りますが、今はRaspberryPiと組み合わせて使うことが多く、お互いにお互いの弱点を補ってくれるので不足はありません。今回のLTCを扱う上ではとても便利です。
それでは基本となる処理方針を考えていきましょう。
LTCの実態である差動バイフェースはシリアル信号の一種ですが、これを専門的に扱うモジュールもライブラリもPIC16系にはありません。高級OSにおけるデバイスドライバに相当する部位から書くのですが、シリアル信号では基底クロックの精度と汎用性が重要になりますから、クロックソースをどうやって作るかを考えてみます。
LTCは1,940~2,400bpsの差動バイフェーズ信号です。これに用いる基底クロックをPIC内で作ります。基底クロックは差動バイフェーズの性質上送信速度の倍ですから3,880~4,800Hzです。
マイコンに与えるクロック(Fosc)は32MHzとします。8MHzの水晶発振子を用い内部の4倍PLLで32HMzとします。1命令クロックはパイプラインの都合でFosc/4となり8MHzです。
基底クロックはPIC内のタイマであるTMR1をコンペアモードで起こします。コンペアモードとは、命令クロックでカウントされるTMR1とCCPxレジスタの値が一致すると割り込みを発生し、TMR1をクリアする機能なので、設定周期を発生させるのに便利な機能です。
高度な分周機能を持ったPLLを用いれば簡単なことですが、8MHzのタイマの単純なカウントだけで必要な基底クロックを起こすにはちょっとした小細工をします。
PICのコンペアモードは、CCPxレジスタに値を設定しておけば、TMR1の値がこれと同じになった瞬間にフラグ(一致フラグ)が立つ機能です。通常はCCPxを一定値で使いますが、一致回数に対し一定の周期でCCPxレジスタの値を増減すれば長い目で見ると辻褄を合わせられます。クロック周期の増減は0.5%未満なので、波形の立ち上がり立下り誤差に吸収される程度だと思います。
LTCは1時間単位で帳尻が合うことを前提にしていますのでその様に計算します。PICマイコンの1時間当たりの総クロックカウント数と、LTCの基底クロックを起こすTMR1の総クロックカウント数が同じになるようなCCPxレジスタの増減規則を見つけたいと思います。
余りを帳消しにする補正を考えます。
[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差1) = 11,520,000] = [1.500] → 切り上げ → [補正周期1 = 2]
[1時間あたりの基底クロック数 = 17,280,000] mod [補正周期1 = 2] = [余り(誤差2) = 2,880,000]
[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差2) = 2,880,000] = [6.00] → 余り無し → [補正周期2 = 6]
補正周期とは、CCPxにレジスタに与えるカウント標準値を補正する基底クロックの周期です。この場合補正値は1としています。
CCPxにレジスタに与えるカウント標準値を基底クロックのカウント2回に1回、6回に1回+1(1,667)するのです。2回と6回では倍数/約数の関係で位相が合ってしまいますから、偶数目で2回周期とし、奇数目で6回周期を取ればいいでしょう。
総カウント数が一致するので1時間あたりの誤差は無いとなります。
[CCPxにレジスタに与えるカウント標準値 = 1,666]
[補正周期1 = 2]
[補正周期2 = 6]
余りを帳消しにする補正を考えます。
[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差1) = 5,754,246] = [3.0・・・03] → 切り上げ → [補正周期1 = 4]
[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期1 = 4] = [余り(誤差2) = 1,438,561.438554800]
[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差2) = 1,438,561.438554800] = [12.000000000055400] → 切り上げ→ [補正周期2 = 13]
[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期2 = 13] = [余り(誤差3) = 110,658.5721903900]
[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差3) = 110,658.5721903900] = [156.00000000936500] → 切り上げ→ [補正周期3 = 157]
[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期3 = 157] = [余り(誤差4) = 704.83166340147700]
[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差4) = 704.83166340147700] = [24,492.00023084700] → 切り上げ→ [補正周期4 = 24,493]
[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期4 = 24,493]] = [余り(誤差5) = 0.028770218230306500]
誤差が1未満になりましたのでここまで
誤差 = 0.028770218230306500 / 28,800,000,000 (水晶発振子の精度からしてもこれ以上頑張っても意味がない)
[CCPxにレジスタに与えるカウント標準値 = 1,666]
[補正周期1 = 4]
[補正周期2 = 13]
[補正周期3 = 157]
[補正周期4 = 24,493]
補正の必要はありません。
[CCPxにレジスタに与えるカウント標準値 = 2,000]
余りを帳消しにする補正を考えます。
[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差1) = 4,608,000] = [3.00] → 余り無し → [補正周期1 = 3]
[CCPxにレジスタに与えるカウント標準値 = 2,083]
[補正周期1 = 3]
クロックはすべての基本ですから、出来るだけ正確を目指したいものです。
受信ではLTCを10バイトのデータにすることが最初の作業でしょう。
そのためにもビットを正確に受信しなければなりません。
ソフトウェア的に処理し、対応範囲を24~30fpsとします。
差動バイフェーズは値が一定でも信号が常に反転していますから、PICではI/O入力の変化割り込みを用いるのが最適でしょう。その名の通り、I/Oの入力が変化すると割り込みが発生する機能です。
PIC内での処理ですから、波長の長短は秒数よりも上記のカウンタのカウント数で考えた方が近道です。可能ならば24fpsでも30fpsでも同じ処理で済ませたいので検討します。
符号 | 24fps | 30fps | ||||
-10% | 0% | +10% | -10% | 0% | +10% | |
0 | 3,787 | 4,166 | 4,583 | 3,029 | 3,332 | 3,666 |
1 | 1,893 | 2,083 | 2,292 | 1,514 | 1,666 | 1,833 |
符号0ならば3,029~4,583です。符号1ならば、2回続けてが条件になりますが、1,514~2,292です。
表の太字にもなりますが、フレームレートに関わらず符号0の最短波長と符号1の最長波長は被りません。デコード処理は24~30fpsで定数も含めて共通化出来るということです。
精度やノイズ耐性を上げるなら設定されたフレームレートに合わせて許容範囲を絞ればいい。
ビットデータを得たなら一時スタックレジスタに保存する。
受け取るのは時刻の刻みにも等しい物なので、正しい長さの信号であるかを評価する意味はあまり無いと思う。同期ワードが出現した瞬間に受信したデータに書かれた時刻が真であるとして良いと思う。
・・・以下、まとめ中。