この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
広告
posted by fanblog
2023年03月31日
Z変換とラプラス変換も同時に処理できる事に気づいた
3月の初めころから頑張って作っていたけど、
1,Z変換式をグラフ表示するツールをpascalで作ってからJavaScriptで動かそう
2,ある程度動いたけど、アナログとの比較の為にラプラス変換のグラフも出来た方がいい
3,まあラプラス変換はZ変換より簡単だからJavaScript側で変更すりゃいいか
4,おお中間コードに変換しない分 半分以下のサイズになったぞ
5,あれ? Z変換も同じように出来るんじゃないか?
6,あZ変換もラプラス変換も違いは小さい。というかe^sがzだった
7,なら一緒に扱えるようにすりゃいいや
という事で いちおう 当初のグラフ表示するまでの予定は達成したけど、なんだか物凄く遠回りしたようでモヤモヤする
z変換とラプラス変換で周波数特性を得るjavascript
2023年03月25日
JavaScriptでラプラス変換の伝達関数を求める
デモの為に最初はフィルタを巡回表示しています。
その為に この画面を表示していると、
ご迷惑をかけたなら、ごめんなさい。
ボタンを押せばしばらくは 巡回が止まります。
上手く表示されていないなら JavaScriptでラプラス変換の伝達関数を求める
2023年03月21日
JavaScriptでGUI
Z変換でグラフ表示する部分がほぼ動くようになった 。
ただスライドバーで特性を動かすとなると画面作りが面倒になる。そこで画面内をGUI的に動かすようにしたい。
その実験として以前作りかけた4つの歯車をマウス操作で動くようにしてみた。
面倒なのはmousemoveにはoffsetXがあるのに touchmoveには無い事。
この歯車のソースコードは
4つの歯車
2023年03月19日
pascalとJavaScript 関数内関数でハマった
Z変換の周波数特性表示の為に 数式処理をpascalコードからJavaScriptの変換作業をしてるのですが
最初クラスで書いてJavaScriptに変換しようとすると大量のthisに溢れたコードで鬱陶しくなり、これはダメだと 関数内関数に変更しました。
問題は数式処理をreplaceのコールバック関数を使った為にpascal側では関数内関数をコールバック出来ない事。
仕方なくpascal側ではreplace関数をexecで展開して呼ぶように修正。
さて大丈夫かと思ったら、大量の実行エラー。原因はクラスメンバー参照。
Pascal側では関数内関数でもselfはそのクラスを示しているし、メンバー参照も出来るのですが
JavaScriptの関数内関数はthisを自動では引き継いでくれないようです。
func1(param1,param2)の代わりに func1.call(this, param1, param2); てな置換が必要。
そうすると短い関数呼び出しが長くなってやはり鬱陶しい。
関数内関数にした事でメンバー数は減っているので
関数の先頭で z:=self;のように代入して関数内関数からはzを参照するように変更しました。
作ったツール でjavascriptに置換して thisを探して 元のpascalにz.を付ける作業をして全体が動きやっとデバッグが出来る状態に。
他にもAND OR は & | にしておけば論理でもバイナリでも問題ないけど not は ~ だと論理式の場合常にtrueになってしまうとか、なかなか厄介です。(notはif while untilで最初に見つけたら!に変換する事にしたけど)
最初クラスで書いてJavaScriptに変換しようとすると大量のthisに溢れたコードで鬱陶しくなり、これはダメだと 関数内関数に変更しました。
問題は数式処理をreplaceのコールバック関数を使った為にpascal側では関数内関数をコールバック出来ない事。
仕方なくpascal側ではreplace関数をexecで展開して呼ぶように修正。
さて大丈夫かと思ったら、大量の実行エラー。原因はクラスメンバー参照。
Pascal側では関数内関数でもselfはそのクラスを示しているし、メンバー参照も出来るのですが
JavaScriptの関数内関数はthisを自動では引き継いでくれないようです。
func1(param1,param2)の代わりに func1.call(this, param1, param2); てな置換が必要。
そうすると短い関数呼び出しが長くなってやはり鬱陶しい。
関数内関数にした事でメンバー数は減っているので
関数の先頭で z:=self;のように代入して関数内関数からはzを参照するように変更しました。
作ったツール でjavascriptに置換して thisを探して 元のpascalにz.を付ける作業をして全体が動きやっとデバッグが出来る状態に。
他にもAND OR は & | にしておけば論理でもバイナリでも問題ないけど not は ~ だと論理式の場合常にtrueになってしまうとか、なかなか厄介です。(notはif while untilで最初に見つけたら!に変換する事にしたけど)
2023年03月16日
閉じなくなったコンソール
少し前 printfデバッグの為にコンソールを使う話を書きましたが、GUIアプリでAllocConsoleでコンソールを開いてFreeConsoleで閉じようとして奇妙な事に気づきました。32bit時代にはFreeConsoleで閉じていた窓がWin11で閉じなくなったのです。
64bitアプリだけかと思いましたが32bitでも同様の状況。
検証1
FreeConsoleして残ったコンソールを閉じた場合 →GUIアプリはそのままです。
検証2
AllocConsole → FreeConsole → AllocConsole とすると2つ目のコンソールが開きます。
2つ目のコンソールを閉じるとGUIアプリは道連れに終了してしまいますが
1つめのコンソールを閉じてもGUIアプリはそのままです。
どちらも
CloseWindowsは効く
DestroyWindowでは終わらない。(手動では閉じるのでWM_CLOSEは当然有効)
これはこれで便利かもしれません。GUIアプリでデバッグ中に表示して即座にFreeConsoleしておけば
間違って閉じてしまってもアプリが道連れ終了になりませんし、複数の表示内容を複数の窓で確認できるようになりす。
そうすると、前回、コンソールの閉じるボタンを無効化する処理はそのままだと不便になります。
FreeConsoleする時は、閉じるボタンの無効化を戻しておく方が便利に使えます。
それは閉じるボタンの無効のような 面倒なコードは必要なくて
GetSystemMenu(MyConsoleWhd, True);
とするだけです。
他のコンソール関係のコードを確認したい場合は→
Lazarusでコンソールに出力
64bitアプリだけかと思いましたが32bitでも同様の状況。
検証1
FreeConsoleして残ったコンソールを閉じた場合 →GUIアプリはそのままです。
検証2
AllocConsole → FreeConsole → AllocConsole とすると2つ目のコンソールが開きます。
2つ目のコンソールを閉じるとGUIアプリは道連れに終了してしまいますが
1つめのコンソールを閉じてもGUIアプリはそのままです。
どちらも
CloseWindowsは効く
DestroyWindowでは終わらない。(手動では閉じるのでWM_CLOSEは当然有効)
これはこれで便利かもしれません。GUIアプリでデバッグ中に表示して即座にFreeConsoleしておけば
間違って閉じてしまってもアプリが道連れ終了になりませんし、複数の表示内容を複数の窓で確認できるようになりす。
そうすると、前回、コンソールの閉じるボタンを無効化する処理はそのままだと不便になります。
FreeConsoleする時は、閉じるボタンの無効化を戻しておく方が便利に使えます。
それは閉じるボタンの無効のような 面倒なコードは必要なくて
GetSystemMenu(MyConsoleWhd, True);
とするだけです。
他のコンソール関係のコードを確認したい場合は→
Lazarusでコンソールに出力
タグ: Win11
2023年03月15日
やっとグラフを描画するJavaScriptが動くようになった
pascal側の case文はcaseの中でbreakすれば外のループが抜けるが、そのまま switchに変換したら ループを抜けてくれない。 caseの外のループ文にラベルを置いて、break ラベルと変換しないといけないようだ。
変換ツールをそういうふうに対応させたが、多重になった時の動作が心配になり、結局出来るだけcase文でbreakはしないように元コードを直す事に。
でグラフ表示がJavaScript側でも出来るようになったので、Lazarus側で作ったZ変換から作った周波数特性数式を入れてみたが
低周波で0dBにならないという事は、数式処理の部分でミスってるようだ。
まだまだ周波数特性表示の完成は遠い
2023年03月11日
久しぶりに数式処理を書いた
Z変換で周波数特性を表示させるJavaScriptを書くためにPascalで先に書いて動くコードをJavaScriptに直す事にした。
数式処理はGIkoBasicをベースにAddSub/MulDivと再帰下降で書いていたのを手直ししていただけなので
正規表現で分解された要素が引数として与えられて処理する方式となるのは初めてのスタイルだ。
async/await を使えば再帰下降のままでも処理出来そうだが、Pascal側にその機能がないので先にコードが書けない。
四苦八苦してとりあえずpascal側である程度動作するコードは書けた。
Lazarusで正規表現を使う例とかで参考になるかもしれないので現時点でのコードを公開してる=>
z変換で周波数特性を得るjavascript作成奮戦記
これからこの千行付近あるコードをJavaScriptに直すのはちょっと頑張らないといけない
数式処理はGIkoBasicをベースにAddSub/MulDivと再帰下降で書いていたのを手直ししていただけなので
正規表現で分解された要素が引数として与えられて処理する方式となるのは初めてのスタイルだ。
async/await を使えば再帰下降のままでも処理出来そうだが、Pascal側にその機能がないので先にコードが書けない。
四苦八苦してとりあえずpascal側である程度動作するコードは書けた。
Lazarusで正規表現を使う例とかで参考になるかもしれないので現時点でのコードを公開してる=>
z変換で周波数特性を得るjavascript作成奮戦記
これからこの千行付近あるコードをJavaScriptに直すのはちょっと頑張らないといけない
タグ: 正規表現
2023年03月05日
LazarusでprintfDebug
Lazarusにはデバッグコンソールがなく GUIアプリだとprintfデバッグが面倒です。
GUI画面が固まる前ならメモ帳でも張り付けて出力出来るのですけどね。
もちろんGUIからでも windows.AllocConsole;でコンソールは開くのですが
その場合 コンソールを手動で閉じてしまうとアプリも落ちてしまいます。
つい邪魔でデバッグ中にコンソールを閉じたつもりでアプリを終了させてデバッグ失敗をなくすために
コンソール窓の右上の[X]を無効にしてしまいます。
それは2か所からの公開ノウハウの組み合わせです。リンクを示しています。
リンク先に感謝を
var MyConsoleWhd: HWND = 0;
MyConsoleBuf:array [0..0] of AnsiChar;
procedure OpenConsole;
var
OldWindowTitle, NewWindowTitle: ansistring;
mHMENU: HMENU;
begin
AllocConsole(); //false=失敗するのは既に開いている時だけ
if MyConsoleWhd = 0 then //初めて呼ばれた時
begin
System.Assign(System.OutPut, 'CONOUT$');
System.ReWrite(System.OutPut);
System.SetTextBuf(System.OutPut,MyConsoleBuf); //バッファがある間は文字が出力されないので
// System.SetTextCodePage(System.OutPut ,GetOEMCP()) ; //これをしても効果ない
// https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/performance/obtain-console-window-handle
NewWindowTitle := format('OpenConsole%15.10f', [now]);
OldWindowTitle := '';
SetLength(OldWindowTitle, 512);
GetConsoleTitleA(@OldWindowTitle[1], 512 - 1); //タイトル文字を保存して
SetConsoleTitleA(pansichar(NewWindowTitle)); //適当なタイトルを付けて
Sleep(40);
MyConsoleWhd := FindWindowA(nil, pansichar(NewWindowTitle)); // 窓ハンドル得る
SetConsoleTitle(pansichar(OldWindowTitle)); //タイトル文字を復元
// https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/896conclosebtn/conclosebtn.html
// [閉じる]ボタンの無効化
if MyConsoleWhd <> 0 then
begin
mHMENU := GetSystemMenu(MyConsoleWhd, False);
RemoveMenu(mHMENU, SC_CLOSE, MF_BYCOMMAND);
end;
end;
end;
コンソールに出力する時、GUIから開いたコンソールではwriteは出来ません。
どうやら stdoutのファイル型 が初期化されていないようです。
上では'CONOUT$'でファイル変数を開くようにしています。(ただしコンソールアプリモードとは挙動が違うようです)
もともとLazarusはUTF8ですからそのままコンソールにwriteで出力すれば文字化けします。
そこで文字化けしない文字列用の出力コマンドの例を
procedure cPutS(s: ansistring);
var
rdSize: DWORD;
begin
OpenConsole; //コンソールのコードページも変更可能だが
// SetConsoleOutputCP(StringCodePage(s));//こうやってもUTF8は文字化けするので
SetCodePage(RawByteString(s),GetOEMCP() ,true); //文字列のコードページを変更する
//せっかく変更しても s+#13#10 と文字列の加算するだけでUTF8に戻るから2行に分ける
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @s[1], length(s), rdSize, nil);
s := #13#10;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @s[1], length(s), rdSize, nil);
//rdSizeは見てない。まあ出力出来なかったらどうしろというのか判らないし
end;
のような関数を別に用意してやります
GUI画面が固まる前ならメモ帳でも張り付けて出力出来るのですけどね。
もちろんGUIからでも windows.AllocConsole;でコンソールは開くのですが
その場合 コンソールを手動で閉じてしまうとアプリも落ちてしまいます。
つい邪魔でデバッグ中にコンソールを閉じたつもりでアプリを終了させてデバッグ失敗をなくすために
コンソール窓の右上の[X]を無効にしてしまいます。
それは2か所からの公開ノウハウの組み合わせです。リンクを示しています。
リンク先に感謝を
var MyConsoleWhd: HWND = 0;
MyConsoleBuf:array [0..0] of AnsiChar;
procedure OpenConsole;
var
OldWindowTitle, NewWindowTitle: ansistring;
mHMENU: HMENU;
begin
AllocConsole(); //false=失敗するのは既に開いている時だけ
if MyConsoleWhd = 0 then //初めて呼ばれた時
begin
System.Assign(System.OutPut, 'CONOUT$');
System.ReWrite(System.OutPut);
System.SetTextBuf(System.OutPut,MyConsoleBuf); //バッファがある間は文字が出力されないので
// System.SetTextCodePage(System.OutPut ,GetOEMCP()) ; //これをしても効果ない
// https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/performance/obtain-console-window-handle
NewWindowTitle := format('OpenConsole%15.10f', [now]);
OldWindowTitle := '';
SetLength(OldWindowTitle, 512);
GetConsoleTitleA(@OldWindowTitle[1], 512 - 1); //タイトル文字を保存して
SetConsoleTitleA(pansichar(NewWindowTitle)); //適当なタイトルを付けて
Sleep(40);
MyConsoleWhd := FindWindowA(nil, pansichar(NewWindowTitle)); // 窓ハンドル得る
SetConsoleTitle(pansichar(OldWindowTitle)); //タイトル文字を復元
// https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/896conclosebtn/conclosebtn.html
// [閉じる]ボタンの無効化
if MyConsoleWhd <> 0 then
begin
mHMENU := GetSystemMenu(MyConsoleWhd, False);
RemoveMenu(mHMENU, SC_CLOSE, MF_BYCOMMAND);
end;
end;
end;
コンソールに出力する時、GUIから開いたコンソールではwriteは出来ません。
どうやら stdoutのファイル型 が初期化されていないようです。
上では'CONOUT$'でファイル変数を開くようにしています。(ただしコンソールアプリモードとは挙動が違うようです)
もともとLazarusはUTF8ですからそのままコンソールにwriteで出力すれば文字化けします。
そこで文字化けしない文字列用の出力コマンドの例を
procedure cPutS(s: ansistring);
var
rdSize: DWORD;
begin
OpenConsole; //コンソールのコードページも変更可能だが
// SetConsoleOutputCP(StringCodePage(s));//こうやってもUTF8は文字化けするので
SetCodePage(RawByteString(s),GetOEMCP() ,true); //文字列のコードページを変更する
//せっかく変更しても s+#13#10 と文字列の加算するだけでUTF8に戻るから2行に分ける
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @s[1], length(s), rdSize, nil);
s := #13#10;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @s[1], length(s), rdSize, nil);
//rdSizeは見てない。まあ出力出来なかったらどうしろというのか判らないし
end;
のような関数を別に用意してやります
2023年03月04日
JavaScriptを学んでゆこう
音の事を説明しようとすると周波数特性とかのグラフを見せないと伝わらない。
静止画ではなく係数がこう変化したらこうなるというグラフを見せたい。
といってwindowsのexeで作ってもウイルス扱いされてダウンロードしてもらえない。
いっぽうJavaScriptはダウンロードの必要もなく、誰にでも見てもらえます。
上の描画はJavaScriptで描いています。描くだけなら少しの知識で出来ます。
問題はGUI処理。
これを学んでゆきたいと考えています。
あ、上の歯車はサイクロイド曲線で描かれていて、4つの歯車で中央の隙間がどうなるのか見たかったのです。
このページで見えないようなら→
4つの歯車
違う歯数を設定したら噛み合ってないとか ひし形の配置とか、そのうち改善させたいと思っていますが未定
タグ: ロータリーエンジン
2023年03月03日
SIMD命令をDelphiでも動かす
Delphiといっても普段使ってるのはDelphi5です。XEあたりまでは飛び飛びのバージョンでも持っていますが、軽くて小さいexeが作れて使用許諾がオンラインでないので仮想環境でも面倒なく使えますからね。
AVX命令で10倍もの速度が出るのならDelphi5でも使ってみたくなります。
問題はDelphi5のアセンブラにはAVXどころかSSEもない事です。
そこでFPCのObjDump(GCCのと同趣旨のもの)を呼び出して アセンブラ命令を DB命令(バイトデータ)に置き換えて見事に使えてしまいました。
Lazarusで作ったSIMD関数をDelphiで使う のページです
このページには ObjDump.exeを呼び出して取り込むツールのソースが入っているので、
何かコンソールアプリ起動して出力を処理したい人は参考にして下さい。
AVX命令で10倍もの速度が出るのならDelphi5でも使ってみたくなります。
問題はDelphi5のアセンブラにはAVXどころかSSEもない事です。
そこでFPCのObjDump(GCCのと同趣旨のもの)を呼び出して アセンブラ命令を DB命令(バイトデータ)に置き換えて見事に使えてしまいました。
Lazarusで作ったSIMD関数をDelphiで使う のページです
このページには ObjDump.exeを呼び出して取り込むツールのソースが入っているので、
何かコンソールアプリ起動して出力を処理したい人は参考にして下さい。