2023年2月 この範囲を時系列順で読む この範囲をファイルに出力する
ArtNet-Engineの入口出口キー操作は触るたびに問題点が見えてきます。なかなか次に進めません。
次の課題は受信スタックです。これは得たデータをレーンと呼ぶ内部的な経路と送信元毎に仕分けしたモノです。8レーン8送信元、64ユニバースの一時保存です。一見データ量が多いようですが32kBです。映像画像に比べたらわずかな量です。
受信毎に本処理まですればいい気もしますが、送信元から送られるデータは時間的に一定ではありませんので、受信の都度本処理までするとややこしくて重くなるのです。
ならば、一定の規則で受信データを整頓し、送信元×レーン毎の入れ子に最新値という形で一時保存してから本処理を行えばシンプルな処理になります。
こんなややこしいことをしてもDMX規格の最大速の1フレーム程度にレイテンシーを抑えようとしています。
もちろんタイムアウトも必要です。DMXはデータが1秒間更新されなければ送信が無くなったと判断する規格ですから受信日時を見て判断します。これは優先度が低い処理ですから優先度が高い処理が実行されない空き時間を用います。極端な話、タイムアウトは1秒が基本でも5秒かかったところで実用上の問題は無いと考えます。そんなにかかることは無いと思いますが、2秒くらいで処理されれば実用だと思います。それ以前にDMXのタイムアウトが1秒ってことを知る人が少ないのですから気にしない。
#[Art-Net]
次の課題は受信スタックです。これは得たデータをレーンと呼ぶ内部的な経路と送信元毎に仕分けしたモノです。8レーン8送信元、64ユニバースの一時保存です。一見データ量が多いようですが32kBです。映像画像に比べたらわずかな量です。
受信毎に本処理まですればいい気もしますが、送信元から送られるデータは時間的に一定ではありませんので、受信の都度本処理までするとややこしくて重くなるのです。
ならば、一定の規則で受信データを整頓し、送信元×レーン毎の入れ子に最新値という形で一時保存してから本処理を行えばシンプルな処理になります。
こんなややこしいことをしてもDMX規格の最大速の1フレーム程度にレイテンシーを抑えようとしています。
もちろんタイムアウトも必要です。DMXはデータが1秒間更新されなければ送信が無くなったと判断する規格ですから受信日時を見て判断します。これは優先度が低い処理ですから優先度が高い処理が実行されない空き時間を用います。極端な話、タイムアウトは1秒が基本でも5秒かかったところで実用上の問題は無いと考えます。そんなにかかることは無いと思いますが、2秒くらいで処理されれば実用だと思います。それ以前にDMXのタイムアウトが1秒ってことを知る人が少ないのですから気にしない。
#[Art-Net]
本業はちょいちょいで終わったのでArtNet-Engineを書き進めました。
ユニバースによる処理時間のムラはサンプルデータとして使っているMAdot2の仕様によるものみたいです。細かくは計測していませんが、8ユニバース出すとして、ユニバース毎に均等の時間割りで送信するのではなく、8ユニバースを一気に送信して長い休みを入れているようです。このため、最初のユニバースでは処理が重くなり、後のユニバースでは処理が軽くなる現象が起きるのだと思われます。主にArtNet-Engineからの送信に影響があったようで、受信したら即送信していたものを一時スタックしてからユニバース毎に均等の時間割りで送信する様にしたところムラが無くなりました。RaspberryPiの送信処理に何か負担がかかっていたのでしょう。
現時点での1フェーズの処理時間は平均して100usec以下です。出現確率が高い例外値が250usecくらいで、極マレに出てくる最大値が900usecくらいです。処理時間が保証されないOSですからこんなもん?。
作りたい物にはなりそうですが、8ユニバース8卓(64ユニバース入力)は厳しい気がします。これに対応するには1フェーズが確実に350usec未満でなければなりませんが、例外値がやってきた時にプリフリーズを起こしそうです。登録できる調光卓(送信元)は8台ですが、同時に使える(HTPミックスの対象となる)のを3-4台くらいにしておけば現実的かもしれません。Art-Netの規格書に「マルチキャストは40ユニバースが上限だと思いますよ」と書いてあるのは伊達じゃないようです。
どの要素が時間を使っているのか不明なので組んで実測しますかね。ダメなら減らすダケです。
ただ、構造体とポインタが使えるとこういったデータ処理は楽です。構造体はPythonのタプルに似ていますがシンプルなのでPythonより書きやすいかもしれません。ポインタは参照渡しですのでデータの扱いが速いのです。それ以前に何をするにも速いですけど。
追記
調整したところ、1ユニバース受信する1フェーズが平均30usec、例外値が200usec程度になりました。
同時に8卓使っても1本のArt-Netに統合する現場はマレだと思いますケド、間に合いそうな数値が出たので、その様に書いて後で調整します。増やすのは大変ですが減らすのは簡単ですから。
送信の間隔はユニバース数と希望fps数から自動計算にしました。将来的にfpsを設定して調整出来れば良いかなと。
#[Art-Net] #C言語
ユニバースによる処理時間のムラはサンプルデータとして使っているMAdot2の仕様によるものみたいです。細かくは計測していませんが、8ユニバース出すとして、ユニバース毎に均等の時間割りで送信するのではなく、8ユニバースを一気に送信して長い休みを入れているようです。このため、最初のユニバースでは処理が重くなり、後のユニバースでは処理が軽くなる現象が起きるのだと思われます。主にArtNet-Engineからの送信に影響があったようで、受信したら即送信していたものを一時スタックしてからユニバース毎に均等の時間割りで送信する様にしたところムラが無くなりました。RaspberryPiの送信処理に何か負担がかかっていたのでしょう。
現時点での1フェーズの処理時間は平均して100usec以下です。出現確率が高い例外値が250usecくらいで、極マレに出てくる最大値が900usecくらいです。処理時間が保証されないOSですからこんなもん?。
作りたい物にはなりそうですが、8ユニバース8卓(64ユニバース入力)は厳しい気がします。これに対応するには1フェーズが確実に350usec未満でなければなりませんが、例外値がやってきた時にプリフリーズを起こしそうです。登録できる調光卓(送信元)は8台ですが、同時に使える(HTPミックスの対象となる)のを3-4台くらいにしておけば現実的かもしれません。Art-Netの規格書に「マルチキャストは40ユニバースが上限だと思いますよ」と書いてあるのは伊達じゃないようです。
どの要素が時間を使っているのか不明なので組んで実測しますかね。ダメなら減らすダケです。
ただ、構造体とポインタが使えるとこういったデータ処理は楽です。構造体はPythonのタプルに似ていますがシンプルなのでPythonより書きやすいかもしれません。ポインタは参照渡しですのでデータの扱いが速いのです。それ以前に何をするにも速いですけど。
追記
調整したところ、1ユニバース受信する1フェーズが平均30usec、例外値が200usec程度になりました。
同時に8卓使っても1本のArt-Netに統合する現場はマレだと思いますケド、間に合いそうな数値が出たので、その様に書いて後で調整します。増やすのは大変ですが減らすのは簡単ですから。
送信の間隔はユニバース数と希望fps数から自動計算にしました。将来的にfpsを設定して調整出来れば良いかなと。
#[Art-Net] #C言語
本業もやらねばなりませんがArtNet-Engineも進めたい。
ArtNet-Engineの課題はデータ処理の構成です。
まずは入力です。同じネットワークに複数の調光卓を繋ぐことは出来ますが、ユニバースの重複によるトラブルには対策が必要です。
送信元IPアドレスで仕訳けることが基本になると思いますが、どうせなら選択しつつマージしてしまおうかと。
フェスなどでは複数の調光卓を設置して使い分けるのはよくあることです。単純な差し替えとかネットワーク切り替え機などを使ってもいいのですが、選択とマージ(HTPミックス)が出来たらそれはそれでいいかなと。バックアップ卓を併設することも出来るし。
内部的には8ユニバースのパッチを考えていますが卓も8台想定します。64ユニバースの交通整理をするのでRaspberryPiの処理能力で間に合うのかわかりませんがダメなら数を減らします。
当面は送信元の仕分けと64ユニバースを8ユニバースにマージする処理を書きます。
処理の構造をどうするか考えていますが、データの保存には構造体配列や構造体の中に構造体を入れるなど複雑な変数構成が必要になりそうです。
Pythonとは違い、for文が速いC言語なら繰り返しと条件分岐を織り交ぜた処理も書きやすそうです。C言語の習得の難所でもあるポインタもこういった処理では効果を発揮します。
#[Art-Net] #C言語
ArtNet-Engineの課題はデータ処理の構成です。
まずは入力です。同じネットワークに複数の調光卓を繋ぐことは出来ますが、ユニバースの重複によるトラブルには対策が必要です。
送信元IPアドレスで仕訳けることが基本になると思いますが、どうせなら選択しつつマージしてしまおうかと。
フェスなどでは複数の調光卓を設置して使い分けるのはよくあることです。単純な差し替えとかネットワーク切り替え機などを使ってもいいのですが、選択とマージ(HTPミックス)が出来たらそれはそれでいいかなと。バックアップ卓を併設することも出来るし。
内部的には8ユニバースのパッチを考えていますが卓も8台想定します。64ユニバースの交通整理をするのでRaspberryPiの処理能力で間に合うのかわかりませんがダメなら数を減らします。
当面は送信元の仕分けと64ユニバースを8ユニバースにマージする処理を書きます。
処理の構造をどうするか考えていますが、データの保存には構造体配列や構造体の中に構造体を入れるなど複雑な変数構成が必要になりそうです。
Pythonとは違い、for文が速いC言語なら繰り返しと条件分岐を織り交ぜた処理も書きやすそうです。C言語の習得の難所でもあるポインタもこういった処理では効果を発揮します。
#[Art-Net] #C言語
オレメモ
ANSIエスケープシーケンスにおいてカーソルの表示/非表示を定義。
RaspberryPi 4B / Rasbian11_32bit / コンパイラ:OS標準gcc
\e[?25h カーソルの表示
\e[?25l カーソルの非表示
相変わらずの不思議な呪文。
#C言語
ANSIエスケープシーケンスにおいてカーソルの表示/非表示を定義。
RaspberryPi 4B / Rasbian11_32bit / コンパイラ:OS標準gcc
\e[?25h カーソルの表示
\e[?25l カーソルの非表示
相変わらずの不思議な呪文。
#C言語
各所の処理タイミングで難儀しましたが、第1フェーズと呼んでもいい段階は終わりました。
まとまったのは次の通り。
1)Art-Netを受信してデコード。
2)エンコードして送信。
3)受信値を表示。
4)カーソルキーでユニバースを切り替えるなど、キーボードによる画面操作。
この程度ではありますが、これから先の基本が多く含まれているのでかなりの進歩だと自画自賛。
スッキリした画面に値がキレイに表示されると気持ち良いです。
ちなみに、画面表示を除く主処理1フェーズの所要時間は平均150usec、最大600usecくらいです(30fps:8ユニバースのArt-Netを受信/デコード/エンコード/送信する処理)。Pythonに比べたら圧倒的に速い。
今後機能を追加してどれくらい重くなっていくのかは未知数ですが、現時点では期待値込みの次第点でしょう。
次はデータ処理の本丸です。
Pythonである程度作れた処理ですが、Pythonならではの便利機能が使えないなら私にとってかなり難しいことなので、処理の手順をキッチリ考えたいと思います。
追記
処理タイミングを調整したところ1フェーズの処理時間が50usec程度減りました。小さな数値ですが比率としては大きい。
不思議なのは、受信している8ユニバース中、0ユニバースに比べ7ユニバースの処理が倍くらい速く処理時間の変動が少ないことです。出力のフレームレートをDoctorMXで計測すると同じ値なので謎です。今は動いているバグですと後々問題になりそうそうなので確認しますが、速いユニバースは1フェーズ90usec前後で安定して動いているのでこれが平均になれば御の字です。この数値で揃えば現在考えている最大規模も処理出来ると思います。
#[Art-Net]
まとまったのは次の通り。
1)Art-Netを受信してデコード。
2)エンコードして送信。
3)受信値を表示。
4)カーソルキーでユニバースを切り替えるなど、キーボードによる画面操作。
この程度ではありますが、これから先の基本が多く含まれているのでかなりの進歩だと自画自賛。
スッキリした画面に値がキレイに表示されると気持ち良いです。
ちなみに、画面表示を除く主処理1フェーズの所要時間は平均150usec、最大600usecくらいです(30fps:8ユニバースのArt-Netを受信/デコード/エンコード/送信する処理)。Pythonに比べたら圧倒的に速い。
今後機能を追加してどれくらい重くなっていくのかは未知数ですが、現時点では期待値込みの次第点でしょう。
次はデータ処理の本丸です。
Pythonである程度作れた処理ですが、Pythonならではの便利機能が使えないなら私にとってかなり難しいことなので、処理の手順をキッチリ考えたいと思います。
追記
処理タイミングを調整したところ1フェーズの処理時間が50usec程度減りました。小さな数値ですが比率としては大きい。
不思議なのは、受信している8ユニバース中、0ユニバースに比べ7ユニバースの処理が倍くらい速く処理時間の変動が少ないことです。出力のフレームレートをDoctorMXで計測すると同じ値なので謎です。今は動いているバグですと後々問題になりそうそうなので確認しますが、速いユニバースは1フェーズ90usec前後で安定して動いているのでこれが平均になれば御の字です。この数値で揃えば現在考えている最大規模も処理出来ると思います。
#[Art-Net]
諸々イイ感じに書き進められていますが、処理タイミングという一見簡単そうで実は面倒なことに取り組んでいます。
先日作ったキー入力処理とArt-Net処理を混ぜているのですが、それぞれに合った時間間隔で実行しないといけません。キー入力は100msec、Art-Netは100usecです。求められる処理間隔が3桁も違うので同じ時間間隔ではどちらかが破綻します。それぞれをそれぞれの時間間隔で実行するにはどうするか。他の処理を止めること無く処理を続けるにはどうするか。
基本は前回処理の日時と現在日時の差から経過時間を評価する方法です。一定の時間間隔で処理を呼ぶのではなく、呼ばれても経過時間が要求未満なら何もしない方法です。signal()を用いて一定時間間隔で関数を実行させるのが王道でしょうが、singal()ですと終わっているべき他処理のチェックが必要になるのでどっちもどっちです。私の書き方が悪いのかもしれませんが、signal()を多用するとバグの原因になりやすいようです。
なんにしても前回処理からの経過時間で対策してみます。そのために必要なのは現在日時の取得です。POSIX時間と呼ばれる1970年1月1日0時0分0秒からの経過秒数を取得出来るのでこれを用います。50マイクロ秒くらいの分解能が欲しいので秒単位では不足しますが、精度はともかく1ナノ秒単位で値を得られますから十分です。
下記はその値を取得するテストプログラムです。
秒とナノ秒が別々の変数で得られるので、評価を簡単にするためにひとまとめにします。ただし、int型は4バイト長(OSが32bitの場合)のためデータ長が不足しますので、8バイト長(OSが32bitの場合)の unsigned long long int型を用います。2038年問題はとりあえず気にしない。。。
Raspberry Pi 4B / Rasbian11_32bit(blueseye) / コンパイラ:OS標準gcc
#include <stdio.h>
#include <time.h>
int main( int argc, char *argv[] ) {
struct timespec now ;
unsigned long long int now_nsec ;
// 現在POSIX時を取得
clock_gettime( CLOCK_REALTIME, &now ) ; // 現在POSIX時間値を取得
now_nsec = ( unsigned long long int )now.tv_sec * 1e9 // unsigned long long int型(8バイト長int)変数に
+ now.tv_nsec ; // 取得値をひとまとめにする(nsec)
// 確認表示
printf( "%11ld.%09ld sec.\n", now.tv_sec, now.tv_nsec ) ; // 取得値を表示
printf( "%21lld nsec.\n", now_nsec ) ; // ひとまとめにした数値を表示
// 終了
return 0 ;
}
※ このブログシステムでは#や[が機能文字扱いなので、上記ではこれらを全角文字で書いています。空白も全角です。
◆ 参考
時間情報の取得方法と扱い方
取得に必要なのは「// 現在POSIX時を取得」以下の2行(表記は3行)です。
実際の処理では、取得した秒とナノ秒を合わせた数値がnow_nsec入りますので現在日時値とし、同じ方法で前回の処理で取得した値との差で経過時間を評価します。単位がnsecなら1秒は1000000000(1e9)ですから、100msecは100000000(1e8)、100usecは100000(1e5)です。良い意味で処理が速いC言語では多用すべき手法です。
関数化・ライブラリ化するとソースは美しいですが、2行で出来ることなので都度の直書きでもいいかなと。将来、2038年問題に対策しやすくしておくならライブラリ化しといた方がいいけど。
PICのアセンブラでも近いことをしていますが、それがPICで様々なことを実現出来ている要因だったりします。処理タイミングの管理はとても重要です。
#C言語
先日作ったキー入力処理とArt-Net処理を混ぜているのですが、それぞれに合った時間間隔で実行しないといけません。キー入力は100msec、Art-Netは100usecです。求められる処理間隔が3桁も違うので同じ時間間隔ではどちらかが破綻します。それぞれをそれぞれの時間間隔で実行するにはどうするか。他の処理を止めること無く処理を続けるにはどうするか。
基本は前回処理の日時と現在日時の差から経過時間を評価する方法です。一定の時間間隔で処理を呼ぶのではなく、呼ばれても経過時間が要求未満なら何もしない方法です。signal()を用いて一定時間間隔で関数を実行させるのが王道でしょうが、singal()ですと終わっているべき他処理のチェックが必要になるのでどっちもどっちです。私の書き方が悪いのかもしれませんが、signal()を多用するとバグの原因になりやすいようです。
なんにしても前回処理からの経過時間で対策してみます。そのために必要なのは現在日時の取得です。POSIX時間と呼ばれる1970年1月1日0時0分0秒からの経過秒数を取得出来るのでこれを用います。50マイクロ秒くらいの分解能が欲しいので秒単位では不足しますが、精度はともかく1ナノ秒単位で値を得られますから十分です。
下記はその値を取得するテストプログラムです。
秒とナノ秒が別々の変数で得られるので、評価を簡単にするためにひとまとめにします。ただし、int型は4バイト長(OSが32bitの場合)のためデータ長が不足しますので、8バイト長(OSが32bitの場合)の unsigned long long int型を用います。2038年問題はとりあえず気にしない。。。
Raspberry Pi 4B / Rasbian11_32bit(blueseye) / コンパイラ:OS標準gcc
#include <stdio.h>
#include <time.h>
int main( int argc, char *argv[] ) {
struct timespec now ;
unsigned long long int now_nsec ;
// 現在POSIX時を取得
clock_gettime( CLOCK_REALTIME, &now ) ; // 現在POSIX時間値を取得
now_nsec = ( unsigned long long int )now.tv_sec * 1e9 // unsigned long long int型(8バイト長int)変数に
+ now.tv_nsec ; // 取得値をひとまとめにする(nsec)
// 確認表示
printf( "%11ld.%09ld sec.\n", now.tv_sec, now.tv_nsec ) ; // 取得値を表示
printf( "%21lld nsec.\n", now_nsec ) ; // ひとまとめにした数値を表示
// 終了
return 0 ;
}
※ このブログシステムでは#や[が機能文字扱いなので、上記ではこれらを全角文字で書いています。空白も全角です。
◆ 参考
時間情報の取得方法と扱い方
取得に必要なのは「// 現在POSIX時を取得」以下の2行(表記は3行)です。
実際の処理では、取得した秒とナノ秒を合わせた数値がnow_nsec入りますので現在日時値とし、同じ方法で前回の処理で取得した値との差で経過時間を評価します。単位がnsecなら1秒は1000000000(1e9)ですから、100msecは100000000(1e8)、100usecは100000(1e5)です。良い意味で処理が速いC言語では多用すべき手法です。
関数化・ライブラリ化するとソースは美しいですが、2行で出来ることなので都度の直書きでもいいかなと。将来、2038年問題に対策しやすくしておくならライブラリ化しといた方がいいけど。
PICのアセンブラでも近いことをしていますが、それがPICで様々なことを実現出来ている要因だったりします。処理タイミングの管理はとても重要です。
#C言語
Art-Netの入口と出口は出来ましたので機能を組みます。C言語に替えた為に処理能力に余裕が出て複座なプロセス処理を多用しなくても良さそうですが、そもそもの処理をどうするか吟味しないといけません。
搭載予定の機能は、ミキサー(マージ)、プリディレイ(入力に施す)、プリプロファイルカーブ、パッチ、ポストプロファイルカーブ、ポストディレイ(出力に施す)です。スタックフェーダー機能はミキサー機能に含まれます。
さて、どうしようかな。
#[Art-Net] #C言語
搭載予定の機能は、ミキサー(マージ)、プリディレイ(入力に施す)、プリプロファイルカーブ、パッチ、ポストプロファイルカーブ、ポストディレイ(出力に施す)です。スタックフェーダー機能はミキサー機能に含まれます。
さて、どうしようかな。
#[Art-Net] #C言語
Art-Netのデコード/エンコードも出来ました。受信した1配列のバイナリデータを分類して構造体に取り込むのがデコード、項目別の構造体から送信用のバイナリデータに変換するのがエンコードです。
実験は受信値をデコードして再エンコードして送信です。照明器具としては何の芸も無い状態ですが、これが出来なきゃ先へは進めません。
topコマンドで処理負荷を見ますと、ダンプ表示ありで23%、ダンプ表示無しで7%くらいです。Art-Netのコア処理は思った以上に軽いですが、画面表示が重いっすね。完成イメージの画面表示はもっと重くなりますので、Art-Netのコア処理は画面表示とは別プロセスにしたいですね。出来ることならArt-Netのコア処理でCPUスレッドを1つ占有したいくらいです。ここは余裕をもって確実にしたい処理ですから。
今のところ製作は順調です。3月末までに1日平均3-4時間程度使えますので、「ArtNet-Engine」と呼ぶコア機能はまとめられそうです。
#[Art-Net] #C言語
実験は受信値をデコードして再エンコードして送信です。照明器具としては何の芸も無い状態ですが、これが出来なきゃ先へは進めません。
topコマンドで処理負荷を見ますと、ダンプ表示ありで23%、ダンプ表示無しで7%くらいです。Art-Netのコア処理は思った以上に軽いですが、画面表示が重いっすね。完成イメージの画面表示はもっと重くなりますので、Art-Netのコア処理は画面表示とは別プロセスにしたいですね。出来ることならArt-Netのコア処理でCPUスレッドを1つ占有したいくらいです。ここは余裕をもって確実にしたい処理ですから。
今のところ製作は順調です。3月末までに1日平均3-4時間程度使えますので、「ArtNet-Engine」と呼ぶコア機能はまとめられそうです。
#[Art-Net] #C言語
Art-Netの送信にも成功しました。
受信値を転送するだけですが、Art-Netデコーダから正常と思われる値が出力されています。
今日は終わりにしますが、大きな課題がクリア出来て大満足です。
ただ、8ユニバースを出力しているdot2が一杯いっぱいの様子。発熱も凄いし画面もコマ送りです。
ちなみにですが、recvfrom()の4番目のパラメータを「MSG_DONTWAIT」にすると受信待ちしません。先達の例では待ちアリの「0」を定義してioctl()に待ち無し(ノンブロッキング)を設定していることが多いのですが、「MSG_DONTWAIT」を使った方がストレスが無い感じ。
で、気付いたのですが、C言語は速い。速いが故の対策が必要になる始末。受送信テストでは終了のためのキー入力やタイムアウトを入れるのが面倒だったのでfor文による一定回数の繰り返しで試したのですが、受信待ちを無くした後はPythonでの実験の際に使った回数では一瞬で終わってしまいます。プログラムが間違っているのかと思う程でした。てことは、あまりにも無意味な回数recvfrom()を呼んでいることになりますので、受信が無い場合は100~500usecくらい待ちを入れた方がいいみたいです。バッファを読みに行っているだけなので気にしなくていいって話もありますが、ANSIエスケープシーケンスを用いた画面表示も適度な待ちを入れないと画面がフリッカーを起こす程です。数か月かかりましたが、C言語を勉強して良かったと思います。遅いのを対策するのは大変ですが、速いのを抑え込むのは比較的簡単ですからね。
ここまで速いとマルチプロセスを使わなくてもいいのではないか?って気持ちも芽生えます。使った方が速さ以外に都合が良いこともあるので使いますケド。
基本的な受送信が確認出来ましたので、関数化しつつArt-Net(正しくはArt-DMX)のデコード/エンコードも書きましょう。
#[Art-Net] #C言語
受信値を転送するだけですが、Art-Netデコーダから正常と思われる値が出力されています。
今日は終わりにしますが、大きな課題がクリア出来て大満足です。
ただ、8ユニバースを出力しているdot2が一杯いっぱいの様子。発熱も凄いし画面もコマ送りです。
ちなみにですが、recvfrom()の4番目のパラメータを「MSG_DONTWAIT」にすると受信待ちしません。先達の例では待ちアリの「0」を定義してioctl()に待ち無し(ノンブロッキング)を設定していることが多いのですが、「MSG_DONTWAIT」を使った方がストレスが無い感じ。
で、気付いたのですが、C言語は速い。速いが故の対策が必要になる始末。受送信テストでは終了のためのキー入力やタイムアウトを入れるのが面倒だったのでfor文による一定回数の繰り返しで試したのですが、受信待ちを無くした後はPythonでの実験の際に使った回数では一瞬で終わってしまいます。プログラムが間違っているのかと思う程でした。てことは、あまりにも無意味な回数recvfrom()を呼んでいることになりますので、受信が無い場合は100~500usecくらい待ちを入れた方がいいみたいです。バッファを読みに行っているだけなので気にしなくていいって話もありますが、ANSIエスケープシーケンスを用いた画面表示も適度な待ちを入れないと画面がフリッカーを起こす程です。数か月かかりましたが、C言語を勉強して良かったと思います。遅いのを対策するのは大変ですが、速いのを抑え込むのは比較的簡単ですからね。
ここまで速いとマルチプロセスを使わなくてもいいのではないか?って気持ちも芽生えます。使った方が速さ以外に都合が良いこともあるので使いますケド。
基本的な受送信が確認出来ましたので、関数化しつつArt-Net(正しくはArt-DMX)のデコード/エンコードも書きましょう。
#[Art-Net] #C言語
Art-Netの受信に成功しました。
先達の情報をいくつか合成しましたが、思った以上に簡単でした。
ネットワークインターフェースの指定も出来ました。
一安心ですが、次は送信しないといけません。
デコード/エンコードをせずに受信値をリレーするだけですが、これが成功しないようでは受信値を加工する努力をしても意味がありません。
#[Art-Net]
先達の情報をいくつか合成しましたが、思った以上に簡単でした。
ネットワークインターフェースの指定も出来ました。
一安心ですが、次は送信しないといけません。
デコード/エンコードをせずに受信値をリレーするだけですが、これが成功しないようでは受信値を加工する努力をしても意味がありません。
#[Art-Net]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105