SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|
2025|01|02|03|04|05|06|

2004-10-23(Sat) SVX入院……

  SVXの修理のために、近所のスバルに行くことにする。その前に、なんとなくボンネット開けたりして、バッテリの電圧を測るってみたら12Vチョイ。……つーか、測ったの初めてだから正常なのかわからん。確かに定格は12Vだけど、セルの回りがシブさからしてかなり弱っているような気がする。

  画像の説明

  相変わらずの症状で車体をガクガクさせつつ、カミさんを乗せてスバルに向かう。ギアがローに落ちないのか、妙に出足が悪いので右折の際にヒヤヒヤしつつ、なんとかスバルに到着。中でお待ちくださいといわれたので、R2のパンフなんかをパラパラしていると、おいらのSVXが出て行くのが見えた。試運転か? なんでもいいけど、あの状態であまりハデに走って欲しくないんだがなぁ。そりゃ走らんと症状も確認できんのはわかる。しかしSVXのATはガラスのATなのだ。そいつを妙なパターンでガシガシとチェンジする今の狂っている状態で走り回ったら、そっちまでイカレるではないか。いや、そりゃ走らんと症状も確認できんのはわかっているのだ。わかっているが、やっぱりATまでイカレたらどーする!? あ゛ー、ぢれんま゛ー。

  画像の説明

  気が気でないまま、ただ帰ってくるのを待つ。待っているとこれまたエラく長い……。やっと帰ってきた。サービスいわく「バッテリが弱ってますね、それ以外はちょっとまだわかりません」とのこと。で、なんでまた黙ってSVXが出て行くかなぁ。試運転ならさっきしたやん。もー、カンベンしてくれー。

  結局、バッテリーを替えてからまた様子を見るということで、入院させることになった。バッテリーの手配には若干時間がかかるとの事。はぁ……ブルー。スバルだけにワールドラリーブルーである。近所なので散歩がてら歩いて帰る。とぼとぼ。図書館に寄って何冊か本を借り、デパートで雨傘(75cm巨大サイズ)を買いつつ、帰宅。別に2週間くらいSVXに乗らないこともあるというのに、なんだこの喪失感は。うがー。

  こんなときは工作でもして気を紛らすに限る。先日修理したワイヤレスヘッドフォンの耳当てでも作ってやろう。カミさんに適当な布をくれといったら、ボロいハンドタオルを出してくれた。これが意外と厚手でこれなら綿を詰めなくてもよさそうだ。型紙を切って、一回り大きく布を切り抜き、周囲を荒く波縫いして、耳当て部分に被せて、糸を絞って終わり。それだけのことだが、意外とうまくいった。

  画像の説明 画像の説明

  早速装着してみると、これがもう思いのほかサイコーである。耳に当たるタオル地がムチャ気持ちいいのだ。音も特に曇ったようには感じない。オーディオマニアにはチャンチャラと笑われてしまいそうなので、さすがにオーデヲ振って(?)見せられないが、こんなかけ心地のいいヘッドホンは他にないぞ。マジで、マジで、マジで。

  あっさり工作……というより裁縫が終わってしまったので、SVXの事を思い出さないよう、今度はメビウスでもイジろう。先日、ACアダプタを一部爆破してしまったので、アダプタのガワを内蔵USBハブとしての再利用すべく計画を進めるのだ。ドリルでガリガリやっては、ハブの位置あわせなんかをしてみたりする。作業中、大地震。おぃおぃ、手元が狂うじゃねぇか、うぜぇ。無視して継続。写真にはないが、メビウスの裏ケースを外してケーブルの配線経路なんかも下見する。

  画像の説明

  が、気がつくとSVXのことが思い出されてブルーに……はっ、そうだッ!! 明日はバッテリーを手土産にスバルにSVXのお見舞いに行こうッ!! そーすれば修理も早まるし、純正のバッテリーより安く済むかもしれない。バッテリーの型式は80D26Rだな。よしッ!! 待ってろよー、マイブラザーッ!!(病気かオレは……)


2009-10-23(Fri) OpenSuSEのRubyもncursesw化する

  ほとんど同じだけれども、一応、SuSEの手順も記録しておく。

opensuse-11.1:/root # cat /etc/SuSE-release 
openSUSE 11.1 (x86_64)
VERSION = 11.1
 
縁起物なので、YaSTでRubyパッケージを「ruby-1.8.7.p72-5.4.1」にアップデートする。
 
opensuse-11.1:/root # wget http://download.opensuse.org/source/distribution/11.1/repo/oss/suse/src/ruby-1.8.7.p72-5.3.src.rpm
 
opensuse-11.1:/root # rpm -ivh ruby-1.8.7.p72-5.3.src.rpm 
 
opensuse-11.1:/root # rpmbuild -bp /usr/src/packages/SPECS/ruby.spec 
error: Failed build dependencies:
	gdbm-devel is needed by ruby-1.8.7.p72-5.3.x86_64
	gperf is needed by ruby-1.8.7.p72-5.3.x86_64
	readline-devel is needed by ruby-1.8.7.p72-5.3.x86_64
	tk-devel is needed by ruby-1.8.7.p72-5.3.x86_64
 
YaSTで各パッケージを導入。こういうトコが、GUIって、却って面倒いな。
 
opensuse-11.1:/root # rpmbuild -bp /usr/src/packages/SPECS/ruby.spec 
 
opensuse-11.1:/root # cd /usr/src/packages/BUILD/ruby-1.8.7-p72/
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72 # cd ext/curses/
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # ruby extconf.rb 
mkmf.rb can't find header files for ruby at /usr/lib64/ruby/ruby.h
 
YaSTで「ruby-devel」を導入。
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # ruby extconf.rb 
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # make
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # diff -c curses.c.org curses.c
*** curses.c.org	Fri Oct 23 20:35:30 2009
--- curses.c	Fri Oct 23 20:47:21 2009
***************
*** 15,20 ****
--- 15,21 ----
  
  #include "ruby.h"
  #include "rubyio.h"
+ #include "locale.h"
  
  #if defined(HAVE_NCURSES_H)
  # include 
***************
*** 1441,1446 ****
--- 1442,1449 ----
  void
  Init_curses()
  {
+ 	setlocale(LC_ALL, "");
+ 
      mCurses    = rb_define_module("Curses");
      mKey       = rb_define_module_under(mCurses, "Key");
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # diff -c extconf.rb.org extconf.rb
*** extconf.rb.org	Fri Oct 23 20:35:30 2009
--- extconf.rb	Fri Oct 23 20:40:12 2009
***************
*** 1,15 ****
  require 'mkmf'
  
  dir_config('curses')
! dir_config('ncurses')
  dir_config('termcap')
  
  make=false
  have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
  have_library("tinfo", "tgetent") or have_library("termcap", "tgetent")
! if have_header(*curses=%w"ncurses.h") and have_library("ncurses", "initscr")
    make=true
! elsif have_header(*curses=%w"ncurses/curses.h") and have_library("ncurses", "initscr")
    make=true
  elsif have_header(*curses=%w"curses_colr/curses.h") and have_library("cur_colr", "initscr")
    curses.unshift("varargs.h")
--- 1,15 ----
  require 'mkmf'
  
  dir_config('curses')
! dir_config('ncursesw')
  dir_config('termcap')
  
  make=false
  have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
  have_library("tinfo", "tgetent") or have_library("termcap", "tgetent")
! if have_header(*curses=%w"ncurses.h") and have_library("ncursesw", "initscr")
    make=true
! elsif have_header(*curses=%w"ncurses/curses.h") and have_library("ncursesw", "initscr")
    make=true
  elsif have_header(*curses=%w"curses_colr/curses.h") and have_library("cur_colr", "initscr")
    curses.unshift("varargs.h")
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # make distclean
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # ruby extconf.rb
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # make
 
opensuse-11.1:/usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses # cd /usr/lib64/ruby/1.8/x86_64-linux
 
opensuse-11.1:/usr/lib64/ruby/1.8/x86_64-linux # mv curses.so curses.so.org
 
opensuse-11.1:/usr/lib64/ruby/1.8/x86_64-linux # cp /usr/src/packages/BUILD/ruby-1.8.7-p72/ext/curses/curses.so .
 
  1 #!/usr/bin/ruby
  2 
  3 require "curses"
  4 
  5 Curses.init_screen
  6 begin
  7   s = "こんにちは、世界!"
  8   Curses.setpos(Curses.lines / 2, Curses.cols / 2 - (s.length / 2))
  9   Curses.addstr(s)
 10   Curses.refresh
 11   Curses.getch
 12 ensure
 13   Curses.close_screen
 14 end
 
こんにちは、世界!

2011-10-23(Sun) uPC2002アンプ、動作

  今日は朝からガキのイベントに付き合って散歩(スタンプラリー)に出かける。と、偶然、会場でミニ四駆のイベントを見て驚いた。恐ろしく速い。飛んできて、当たったら、ケガするレベル。でも、あれだけ速いからこそ、趣味として取り組む余地があるのだろうな。なるほどね。

  帰宅して、風呂はいって、ハンモックで昼寝。最近、休日は昼寝するのが日課になりつつある。1時間強で起きる。さて、飯を食って、アンプの仕上げだ。

  クリアケースに入れるので、見た目に配慮して、配線の処理も手を抜けない。丹念に、熱収縮チューブで各端子を覆う。

  なお、今回、ずーっと前に購入しつつ、放置してあった、巨大オレンジ色LEDを、動作中を示すランプとして使ってみた。相手がアンプなこともあり、真空管を気取って、天辺と足下にメタルテープをあしらう……おぉ、なんか、いい感じ。

  画像の説明

  とりあえず、ちゃんと音も出た。自作すると、音に愛しさを感じる。仕上げはアンプICに取り付けるヒートシンクだが……いくつか取り付けのプランはあるものの……さて、どうするかな。


2013-10-23(Wed) チープなDTMアプリ・改二

  ふと思い立って、三度、以前に自作したDTMアプリを引っ張り出してきた。2年半ぶりくらいだ。当時の環境はFedora12だったようだが、現在はMint15だ。Rubyも1.8から1.9になっている。そして……

$ padsp -d ./melod 
utils/padsp.c: dsp_open()
utils/padsp.c: fd_info_new()
utils/padsp.c: dsp_open() succeeded, fd=5
utils/padsp.c: sample spec: u8 1ch 8000Hz
utils/padsp.c: fixated metrics to 12 fragments, 1024 bytes each.
7fff0009
utils/padsp.c: freeing fd info (fd=5)
utils/padsp.c: Draining.
./melod:24:in `ioctl': integer 3221508106 too big to convert to `int' (RangeError)
	from ./melod:24:in `block in <main>'
	from ./melod:17:in `open'
	from ./melod:17:in `<main>'

  ……例によって動かねぇ。さっそくどうにかしてみる。

  まず、前回とエラーの内容が変わっている。発生箇所は、前回と同じく、サウンドデバイスへのioctlではあるが、サウンドデバイス側でなく、Ruby側でエラーこいている感じ。どうも、ioctlへ渡す引数が32bit intとして定義されているのが原因っぽい。

  渡したいのは、0xc004500a(SNDCTL_DSP_SETFRAGMENT)等なので、unsignedでないと通りえない。前回は「勝手に64bit拡張して渡してしまうRuby」側の問題だと思いつつ、padsp側にパッチを当てて回避したが、これではRuby側に修正を入れるほかない……悪化しとるがな。

  どうにかゴマかして通せないかと、負数で渡すようにしてみた。

<   p dsp.ioctl(0xc004500a, x)                                  # SNDCTL_DSP_SETFRAGMENT
---
>   p dsp.ioctl(0xc004500a - 0x100000000, x)                    # SNDCTL_DSP_SETFRAGMENT
$ padsp -d ./melod
utils/padsp.c: dsp_open()
utils/padsp.c: fd_info_new()
utils/padsp.c: dsp_open() succeeded, fd=5
7fff0009
utils/padsp.c: unknowned ioctl 0xffffffffc004500a
utils/padsp.c: freeing fd info (fd=5)
utils/padsp.c: Draining.
./melod:24:in `ioctl': Invalid argument - /dev/dsp (Errno::EINVAL)
	from ./melod:24:in `block in <main>'
	from ./melod:17:in `open'
	from ./melod:17:in `<main>'

  おぉ、前回と同じ結果になった。ゴマかして通すことには成功したといえよう。あとは前回と同じくpadspにパッチを当てれば回避できるだろう……が、Ubuntu系の修正ビルドはやったことがない。やってみる。

  まず、リポジトリの定義ファイルをコピーし、各項目の「deb」を「deb-src」と修正、リポジトリ情報を更新する。

~ # cd /etc/apt/sources.list.d
sources.list.d # cp official-package-repositories.list official-package-repositories.sources.list
sources.list.d # vi official-package-repositories.sources.list
sources.list.d # apt-get update 
sources.list.d # cd

  ビルド用のツールをインストールしつつ、ビルド用ディレクトリを掘ってソースをダウンロードする。

~ # aptitude install dpkg-dev
~ # aptitude install devscripts
~ # mkdir build
~ # cd build
build # apt-get source pulseaudio-utils

  ソースディレクトリに移動して、修正を施し(修正内容は前回と同様)、コミット、チェンジログの追加を行ったあと、ビルドを開始する……

build # cd pulseaudio-3.0/src/utils
utils # vi padsp.c
utils # cd ../..
pulseaudio-3.0 # dpkg-source --commit
Enter the desired patch name: 9999-padsp4ruby.patch
pulseaudio-3.0 # dch -i
  * Add patch to padsp for ruby.
pulseaudio-3.0 # debuild -uc -us

  ……と、大量に不足パッケージを指摘されるので、それらをすべてインストールし、再度、ビルドを開始する。

pulseaudio-3.0 # debuild -uc -us

  パッケージは直上にできているので、padspに関連するものをインストール。

pulseaudio-3.0 # cd ..
build # dpkg -i pulseaudio-utils_3.0-0ubuntu7_amd64.deb
build # dpkg -i libpulsedsp_3.0-0ubuntu7_amd64.deb

  完了。melodが動作することを確認。パッチ生成やリリース管理まで、スクリプトが誘導してくれるので、Fedora系よりUbuntu系の方が多少ラクかな。

  改めて、以前に作曲した曲をmidiファイル化して演奏してみたら、音が残ってしまうようになっていた。どうも、キーオフをサボっているのがマズいらしいので、ひょいひょいと修正。

  パッケージを置いておく。しかし、Ruby1.9へのリライトもだいぶ慣れてきたな。


2015-10-23(Fri) 例のWi-Fiを試してみる

  先日、ハンダ付けは終わらせたのだが、手元には5VのUSB-シリアル変換モジュールしかない。よっこらせっとレベルコンバータを作って接続してみた。

  画像の説明

  画像の説明

  画像の説明

  シリアルアクセスはどうしようかと思ったが、古いMintのArduino IDEのシリアルモニタで十分だった。シリアルモジュール/レベルコンバータを接続、「chmod 666 /dev/ttyUSB*」でパーミッションを変更。Arduino IDEの、ツール、シリアルポートで/dev/ttyUSB0を選択。ツール、シリアルモニタを起動。右下のメニューから、CRおよびLF、115200bpsを選択。ESP8266の電源をON。あとはシリアルモニタから、ATコマンドで、無線LANアクセスポイントに接続すればいい。

  画像の説明

  さて、とりあえず、しょっちゅうLANの接続が切れてうっとおしい、自作のXPort-XBeeルータでも、これで置き換えてみようかな。


2023-10-23(Mon) WebAssemblyでイメージを操作

  というわけで「WebAssemblyのひとつだけの使い道」のプログラミングを始めた。やりたいのは要するにイメージの操作だ。単純な計算を山ほどループで繰り返す。実にWebAssembly向きの処理である。

  いきなりだが、以下が機械語サブルーチン部分。イメージを表すRGBAの羅列を渡すと、GとBを抜いてくれるというもの。だいぶカリカリにチューン済み。結局、ループの最適解は減算&非ゼロ判定だな。それはそうと、見慣れないニーモニックが入っている。

(module
    (import "js" "mem" (memory $mem 1))
 
;;  filter(ソースの末尾 + 1 のアドレス)
    (func (export "filter") (param $src_adr i32)
        (local $dst_adr i32)
 
        push        src_adr                     ;; dst_adr = src_adr << 1
        i32.push    1
        i32.shl
        pop         dst_adr
 
loop1:  loop
 
        push        dst_adr                     ;; dst_adr -= 4
        i32.push    4
        i32.sub
        pop_push    dst_adr                     ;; [ dst_adr
 
        push        src_adr                     ;; src_adr -= 4
        i32.push    4
        i32.sub
        pop_push    src_adr                     ;; [ dst_adr src_adr
 
        i32.load                                ;; [ dst_adr color
        i32.push    0xFF0000FF                  ;; [ dst_adr color mask
        i32.and                                 ;; [ dst_adr color
        i32.store                               ;; [
 
        push        src_adr
        jp_nz       loop1                       ;; src_adr != 0 loop
 
        end
    )
)

  つうか、ちょっとは努力をしたつもりなのだが「i32.const」とか「local.set」とか「local.get」とか……ダメだわ。まったく頭に入ってこない。まったくスタックに出し入れしている感じが湧かない。結局、だいぶ前にZ80ライクニーモニックからPICニーモニックに変換するRubyスクリプトを書いた時と同じく、Z80ライクニーモニックからWebAssemblyのwat形式に変換するRubyスクリプトを書いてしまった。PIC用に作ったそれに比べれば、恐ろしく単純な変換しかしていないが、自分にはそれで十分にわかりやすく書ける。はて、自分は頭が固いのか柔らかいのか、どっちなのだろう……ゼッパチの魂百まで。怖い。

#!/usr/bin/env ruby
# coding: utf-8
 
wat80src = ARGV[0]
 
file_in = open(wat80src, 'r')
file_out = open(wat80src.gsub(/\.[^.]+$/, '') + '.wat', 'w', 0444)
 
file_in.each {|line|
    break if(line =~ /^__END__$/)
 
    unless(line =~ /^#/)
        line.chomp!
        if(line =~ /^(\w+):\s*(\w+)(\s*.*)/)                    # loop1:        loop
            line = "\t\t%s\t\t$%s%s" % [$2, $1, $3]
        end
        if(line =~ /^(\s+br\w*)\s+(\w+)(\s*.*)/)                #   br_if       loop1
            line = "%s\t\t$%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+)jp_nz\s+(\w+)(\s*.*)/)                #   jp_nz       loop1
            line = "%sbr_if\t\t$%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+\w+)\.push\s+([\d-]+)(\s*.*)/)         #   i32.push    10
            line = "%s.const\t\t%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+)pop\s+(\w+)(\s*.*)/)                  #   pop         i
            line = "%slocal.set\t\t$%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+)push\s+(\w+)(\s*.*)/)                 #   push        i
            line = "%slocal.get\t\t$%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+)pop_push\s+(\w+)(\s*.*)/)             #   pop_push    i
            line = "%slocal.tee\t\t$%s%s" % [$1, $2, $3]
        end
        if(line =~ /^(\s+)call\s+(\w+)(\s*.*)/)                 #   call        log
            line = "%scall\t\t$%s%s" % [$1, $2, $3]
        end
         line += $/
    end
 
    file_out.write line
}

  HTMLはこう。JavaScriptは外に出した。

<HTML>
    <HEAD>
        <TITLE>WebAssembly Graphics Test</TITLE>
    </HEAD>
    <BODY>
        <CANVAS id='canvas1' width='512' height='384'></CANVAS>
        <SCRIPT type='text/javascript' src='graphics.js'></SCRIPT>
    </BODY>
</HTML>

  で、例によって、JavaScriptはCoffeeScriptに書き直した。CoffeeScriptでasyncやawaitはどう書くのかと思ったら、awaitが含まれる関数は、自動的にasyncを付けてくれるらしい。CoffeeScript 1.xではダメで、2.0以上が必要なようだが。

'use strict'
 
# ソースイメージを読み込む
image_element = new Image
image_element.src = 'gra2.png'
 
# ソースイメージの読み込み完了を待つ
prep = ->
    if(!image_element.complete)
        setTimeout(prep, 100)
    else
        main()
 
main = ->
    screen_canvas_element = document.getElementById('canvas1')
    screen_context = screen_canvas_element.getContext('2d')
 
    # 枠描画、ソースイメージを描画
    screen_context.fillStyle = 'lightgray'
    screen_context.fillRect( 0,  0, image_element.width + 32, image_element.height + 32)
    screen_context.fillStyle = 'gray'
    screen_context.fillRect(16, 16, image_element.width, image_element.height)
    screen_context.drawImage(image_element, 16, 16)
    console.log('image_element:', image_element)
 
    # ソースイメージをデータ化
    work_canvas_element = document.createElement('canvas')
    work_canvas_element.width  = image_element.width
    work_canvas_element.height = image_element.height
    work_context = work_canvas_element.getContext('2d')
    work_context.drawImage(image_element, 0, 0)
#   source_image = work_context.getImageData(0, 0, image_element.width, image_element.height)
    source_bytes = work_context.getImageData(0, 0, image_element.width, image_element.height).data
    source_longs = new BigUint64Array(source_bytes.buffer, 0, source_bytes.length >> 3)     # コピーの高速化のために共用体化
#   console.log('source_image:', source_image)
    console.log('source_bytes:', source_bytes)
 
    # ワークメモリを確保
    work_memory = new WebAssembly.Memory({ initial: 1, maximum: 1 })    # 1 PAGE = 64 KB
    work_bytes = new Uint8ClampedArray(work_memory.buffer, 0, source_bytes.length)
    work_longs = new BigUint64Array(work_memory.buffer, 0, source_longs.length)             # コピーの高速化のために共用体化
 
    # ソースイメージデータをワークメモリにコピー
    for p in [0...source_longs.length]
        work_longs[p] = source_longs[p]
 
    # wasmをロード、メモリ操作(イメージデータの加工生成)を実行
    importObjects = {
        js:         { mem: work_memory },
        console:    { log: (arg) => console.log(arg) },
    }
    obj = await WebAssembly.instantiateStreaming(fetch('graphics.wasm'), importObjects)
    obj.instance.exports.filter(source_bytes.length)
 
    # 生成データをイメージ化
    filtered_bytes = new Uint8ClampedArray(work_memory.buffer, source_bytes.length, source_bytes.length)
    filtered_image = new ImageData(filtered_bytes, image_element.width, image_element.height)
    console.log('filtered_bytes:', filtered_bytes)
    console.log('filtered_image:', filtered_image)
 
    # スプライト(=キャンバス要素)を生成
    sprite_canvas_element = document.createElement('canvas')
    sprite_canvas_element.width  = image_element.width
    sprite_canvas_element.height = image_element.height
    sprite_context = sprite_canvas_element.getContext('2d')
    sprite_context.putImageData(filtered_image, 0, 0)
 
    # 枠描画、スプライトを描画
    screen_context.fillStyle = 'lightgray'
    screen_context.fillRect( 0, 64, image_element.width + 32, image_element.height + 32)
    screen_context.fillStyle = 'gray'
    screen_context.fillRect(16, 80, image_element.width, image_element.height)
    screen_context.drawImage(sprite_canvas_element, 16, 80)
    console.log('sprite_canvas_element:', sprite_canvas_element)
 
prep()

  結構、長い処理になってしまった。仕様上、何度も変換する必要があるのが面倒くさい。

  • 元となるpngを内部CANVASに描き、getImageDataでUint8ClampedArrayの形で取り出す。
  • それをWebAssembly.Memoryの領域にコピーする。
  • WebAssemblyの側でフィルタ処理を行う。
  • WebAssembly.Memoryの領域にUint8ClampedArrayの枠を被せて、ImageDataとして取り込む。
  • それを新たにスプライトとして扱うCANVASにputImageDataで描く、までが準備作業。

  最後に、表示されているCANVASに、drawImageでスプライトCANVASを重ねて完成だ。結果はこんな感じ。

  画像の説明

  というわけで「WebAssemblyのひとつだけの使い道」のプログラミングは成功。よっしゃよっしゃ。任務完了……ではない。実は今回のヤツも習作で、最終目標はもう一歩先にある。もうちっとだけ続くんじゃ。


2024-10-23(Wed) 聖地巡礼帰宅

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  画像の説明

  総走行距離は911.2km。