Web Audio API 備忘録

Web Audio APIで色々遊んだメモ。 サイン波を鳴らす HTMLファイルを作成。適当にindex.htmlとしておく。 1 2 3 4 5 6 7 8 9 <html> <head> <meta charset="utf-8"> </head> <body> <button id="play_btn">play</button> <script src="script.js"></script> </body> </html> script.jsは以下のようにしておく。 1 2 3 4 5 6 7 8 const audioContext = new AudioContext(); const oscillatorNode = audioContext.createOscillator(); oscillatorNode.connect(audioContext.destination); document.getElementById('play_btn') .addEventListener('click', function() { oscillatorNode.start(); }, false); これで、“play” ボタンを押すとサイン波が再生される(音量に注意)。 説明 Web Audio APIの枠組みでは、色々な音やエフェクトをノードとして繋いでいく。最終的な出力を担うノードはAppContext.destinationである。 まずAudioContextのインスタンスを作成する。このContextというのはプログラミングをやっていると色々なところで現れるが (Canvas要素に描画する際にもgetContextが出てくるし、WinAPIだとデバイスコンテキストハンドル、AndroidアプリのプログラミングでもContextがある)、自分は「Audioについて色々な情報を提供してくれるオブジェクト」くらいの理解をしている。 1 const audioContext = new AudioContext(); 続いて、音源としてOscillatorNodeを作成し、繋いでやる。 1 2 const oscillatorNode = audioContext....

2021-12-24 · (updated 2021-12-24) · 6 min · 1165 words

Pythonを使った(静的)ページの画像のURL取得

Webページの画像だけを手っ取り早く取得したい場合にどうすれば良いのかを考えた。 これを行うプログラムをPythonで取得する。 この記事で作成したプログラムはGitHubのRepositoryに公開した。 前提 Pythonのバージョンは3.10を想定。 この記事では外部ライブラリとして Requests 2.26.0 Beautiful Soup 4.10.0 tqdm 4.62.3 w3lib 1.22.0 を使う。この記事のコードを動かす場合はpipコマンドなどでインストールしておく。 方針 やることは案外単純である。 WebページのHTMLデータを取ってくる。 img要素を探して、そのsrc属性を取ってくる。 scheme、netlocが無かったらそれを付加して、完全なURLにする。 1はRequests、2はBeautiful Soupを使えば良いだろう。 3は思ったより複雑である。src属性に入っているパスには、 URL: http://foo.org/bar/hoge.png スキームが省略されている: //foo.org/bar/hoge.png 絶対パス: /bar/hoge.png 相対パス: ../bar/hoge.png データURL: data:image/png;base64,... など色々ある。 これらのフォーマットを統一して完全なURLにするのは面倒であるが、幸運にもurllib.parse.urljoinという関数があったのでこれを使う (余談: 初め、urljoinの存在を知らずに自前でURLの変換機能を実装してしまった。学びにはなったが時間を費やした…)。 ついでの機能として、「特定の要素の中に含まれているimg要素のURLを取得する」ことも考える。 これはCSSセレクタとして指定できるようにする。 まとめると、画像のURLを取得する関数は以下のようなインターフェースとなる。 1 2 def get_img_urls(url: str, selector: Optional[str]=None) -> list[str]: pass # これから実装する URLとセレクタを引数にとり、img要素のURLのリストを返す関数である。 ついでに画像ダウンロードのためのCLIや、画像を閲覧するWebアプリなどが作れたら良い。 プロジェクトの構造 Pythonでモジュールを作ったことがないため、正しい作り方が分からないが、とりあえず以下のような構成にしてみる。 細かいディレクトリの構成は各節で述べる。 1 2 3 4 5 6 7 8 9 10 11 12 /project | +--+ getimg/ | +--+ commandline/ | +--+ viewer/ | +--+ tests/ +-- __init__....

2021-12-09 · (updated 2021-12-16) · 8 min · 1516 words

neovimのプラグインがうまく動かなかったので原因を探した話

(2021/12/25追記) この記事で話題にした問題は最新のddc-nvim-lspで修正されている。こちらのissue及びこちらのcommitを参照。もっとも、この記事を書いてから大分経ったため、ddc_nvim_lsp.luaのソースコードも今では大分変わっている。 以下の文章のまとめ バージョン違いには注意する ddc-nvim-lspは2021/10/1時点では、neovim 0.5.0を想定して作られているプラグインである。しかし自分はneovim 0.5.1を使ってしまっていた。neovim 0.5.1からlsp handlerの引数に破壊的変更があったため、LSPの補完が効かなかった。 究明に当たってDockerを触ったり、Luaを触ったり、ドキュメントを漁ったりして色々糧にはなったので、記録しておく。 何が起きたのか まず、プラグインの管理にはShougo/dein.vimを使った。 neovimのbuildin LSPを使ってLSPが使える環境を構築した。設定に当たって以下のプラグインを導入した。 neovim/nvim-lspconfig 入力補完はShougo/ddc.vimを使った。それにあたって以下のプラグインを導入した。 vim-denops/denops.vim: ddc.vimがDenoの機能を使うため必要。 Shougo/ddc-matcher_head Shougo/ddc-sorter_rank Shougo/ddc-around Shougo/ddc-nvim-lsp 最後のddc-nvim-lspがうまく動かなかった. Language Serverとしてpyrightを導入したのだが、実際にPythonのファイルで入力補完を試したところ,ddc-aroundの補完は反応するが,ddc-nvim-lspの補完候補が現れなかった。 Dockerを使って再現性を検証する まず、 何か他のプラグインが邪魔しているのではないか Macという環境だから問題なのだろうか という仮説を立てた。そのためには、何も無い素のneovimの環境を作る必要があると考えた。そこで、環境をDockerで構築しようと考えた。 Docker環境の構築 適当なディレクトリを作って、そこにDockerfileとdocker-compose.ymlを作成する。 Dockerfileを以下のようにする。ベースイメージはanatolelucet/neovimにした。この時点でdeinを導入する。コマンドはdeinのQuick startを参照した。deinのインストールにあたってcurl、gitコマンドが必要なので、ここで導入する。 1 2 3 FROM anatolelucet/neovim:stable-ubuntu RUN apt-get update && apt-get install -y curl git RUN curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh && sh ./installer.sh ~/.cache/dein neovimの設定ファイルはコンテナ外で編集できるようにしておく。同ディレクトリにディレクトリ.config/nvim/を作成し、その上で、docker-compose.ymlを以下のようにする。 1 2 3 4 5 6 7 8 version: '3' services: nvim: build: ....

2021-10-01 · (updated 2021-12-15) · 3 min · 586 words

Elmでテトリスを作った話

Elmでテトリスを作った。この記事では実装にあたって考えたポイントをメモしておく。 コードは説明のために断片的に載せる。 製作物 ここで遊べる. Repositryはこちら。 実装しなければいけない処理 大まかに作らなければいけないのは以下の処理. ボード・テトリミノのデータ構造 テトリミノの出現・回転・落下・固定 テトリミノの衝突判定 ラインがそろった時に消滅する処理 ゲームオーバー処理 キー操作 画面描画 この中からいくつかの項目について説明する。 ボードのデータ構造 ボードの落とす場は10x20のブロックで構成されている。 壁をボードに含めるかどうか、上部にマージンを設けるかどうかで、実際のボードサイズは変わる。 まず、ボードのブロックをセルと呼ぶことにする。セルを次のように定義する。Colorは適当に定義しておく。 1 2 3 type Cell = Block Color | Empty このセルを使ってボードを定義したいが、悩ましい選択が現れる。 セルを要素に持つList。セルの座標はリストの添字で判断する。 (座標, セル)を要素に持つList。 キーを座標、値をセルとしたDict。 ListをArrayにした実装も考えられる。参考までに、3つは以下のように定義できる。 1 2 3 4 5 6 7 8 type alias Board = List Cell type alias Board = List { pos : Vec Int , cell : Cell } type alias Board = Dict (Vec Int) Cell ボードのデータ構造によって諸々の関数の実装方法が大きく変わってくるので、どれを選ぶか慎重になる必要がある。...

2021-08-10 · (updated 2021-08-10) · 8 min · 1571 words

線形回帰メモ 正則化

問題設定 $\bm{y} = (y^{(1)}, y^{(2)}, \ldots, y^{(N)})^T,\ \bm{x}_i = (1, x_1^{(i)}, x_2^{(i)}, \ldots, x_D^{(i)})^T$ とおく。$(\bm{x}_i, y_i),\ i = 1, 2, \ldots, N$ がデータとして与えられている。このとき、入力と出力の間に $$ \begin{aligned} y &= h_{\bm{w}}(\bm{x})\\ &:= w_0 + w_1x_1 + w_2x_2 + \cdots + w_Dx_D\\ &= \bm{w}^T\bm{x} \end{aligned} $$ が成り立つと仮定し、これに適する$\bm{w}$を見つけたい。 (正則化前の)コスト関数 ここで「適する」とは具体的に何なのかというと、ここでは予測とデータとの二乗誤差の和 $$ J(\bm{w}) = \frac{1}{2} \sum_{i=1}^{N} (h_{\bm{w}}(\bm{x}_i) - y^{(i)})^2 $$ が最小となる $\bm{w}$ を求める。この $J$ をここではコスト関数と呼ぶ。 係数 $1/2$ は微分した時に出てくる $2$ を消し去るための便宜的なものであり、つける必然はない。 L1正則化とL2正則化 コスト関数に $\bm{w}_i$ のL1ノルム(の1乗)の項を付けることをL1正則化という。 $$ J_1(\bm{w}) = J(\bm{w}) + \lambda \|\bm{w}\|_1 $$...

2021-08-07 · (updated 2022-01-13) · 6 min · 1134 words

TikZ 備忘録

随時更新。だいぶ量が増えてきたので,いくつかを分割したほうが良いかもしれない. 毎回マニュアルから情報を探すのが面倒なので、基本的なものをここにまとめたい。個人的に気になったことに対しては深堀して補足しているが、細かいことを気にしすぎた結果、TikZやPGFのソースコードを読みに行く羽目になった。 またここに書いてある内容がベストプラクティスとは限らないことに注意。もっと簡単な書き方があるかもしれない。 情報の集め方 ここに載っているものはほぼTikZ/PGFのマニュアルに載っている。 TeX Liveを導入しているなら、コマンドtexdoc tikzで開くはず。これと同じものがCTANの “PGF Manual"のリンクからダウンロードできる。 非公式ではあるが、HTML版のマニュアルも公開されたようだ:The TikZ and PGF Packages この記事では、なるべく参照した情報を記載するようにする。ここに書いてあることが間違っている場合があるので、何かおかしいなと思ったらマニュアルを参照すること。 知らないキーワードや記号が出てきたらマニュアル末尾のindexで探すと良い。 TikZで出来ることを把握したいなら、Part Iのチュートリアルを読んでみるのが有効。もしくはPartIII, Vあたりを流し読みする。PGF Manualはページ数が膨大なため、全部読もうとするのは恐らく得策では無い。目次を眺めながら興味のあるところをつまむのが良いと思う(読み方について、Introductionの1.4 How to Read This Manualも参照)。 既にやりたいことがあるが、TikZで実現する方法が分からない場合は、ググる。英語のキーワードで検索すれば、大抵Stack Exchangeがヒットする。画像検索も有効。 準備 パッケージ読み込み・この記事での記法の注意 TikZはtikzパッケージから読み込める。 1 \usepakcage{tikz} 以降、コードを記載するときはこの記述を省略する。 また、TikZには色々な便利なライブラリが用意されている。例えば座標計算に便利なライブラリであるCalcは次のように読み込む。 1 \usetikzlibrary{calc} 以降、コード中で必要なライブラリがあった場合は、コードの先頭に\usetikzlibraryを記載することにする。 このコマンドは実際にはプリアンブルに書く必要があることに注意。 DVIドライバの指定 必ずクラスオプションにDVIドライバを指定すること。さもなければ、色が出力されなかったり、図形の位置が正確に計算されなかったりする。 以下は、DVIドライバをdvipdfmx、クラスをjsarticleで行う例。 1 \documentclass[dvipdfmx]{jsarticle} クラスオプションにDVIドライバを指定する必要性については、以下のサイトを参照: 日本語 LaTeX の新常識 2021 - Qiita。 色を定義 (TikZの話ではない) TikZではなくxcolorの話だが、大事なのでここで記す。これはtikzパッケージを読み込んだときに自動で読み込まれるようだが、もしxcolor単体で使いたいなら、xcolorパッケージを読み込むこと。 1 \usepakcage{xcolor} 色同士を!で混ぜることができる。例えばred!20!blue!30!whiteと書くと、赤、青、白がそれぞれ20%、30%、(100-20-30)%混ざった色になる。 カラーコードやRGB値などから定義したい場合は\definecolor、既存の色を混ぜて使いたい場合は\colorletを利用。 1 2 \definecolor{mycolor1}{HTML}{888888} # 定義する色名 カラーモデル 色の値 \colorlet{mycolor2}{orange!75!white} # 定義する色名 色 色名に-をつけると補色を表現できる。ただし、ここでの補色はRGBでの補色。例えば-redとすると赤色の補色のシアンとなる。RYBでの補色を使いたい場合は-には頼らず、色を直接\definecolorで指定する必要があると思われる。...

2021-07-30 · (updated 2023-01-19) · 18 min · 3832 words

ロジスティック回帰 メモ

式変形の一部はProbabilistic Machine Learning: An Introductionを参考にしている。 問題設定 データが $N$ 個あり、入力は $\bm{x}_n = (x_{n1}, x_{n2}, \ldots, x_{nD})$、出力は $y_n \in \{ 0, 1 \}$ とする。 このとき、入力 $\bm{x}$ が与えられたとき出力 $y$ を予測したい。 確率モデルの定義 ここでは確率的なモデルを考える。すなわち、 データ $\bm{x}$ が与えられたとき、 $y = 0, 1$ のどちらの確率が高いのかを考える。 $y$ は2値だから、ベルヌーイ分布としてモデル化できる。 $$ p(y ; \mu) = \mu^y (1 - \mu)^{1 - y} $$ これは、$y = 1$ である確率が $\mu$ 、$y = 0$ である確率が $1 - \mu$ であることを意味する。 $\mu$ は確率だから、$0 \le \mu \le 1$ である必要がある。...

2021-07-11 · (updated 2021-12-25) · 7 min · 1430 words

PureScriptで作るBrainfuckインタプリタ 4/4 Halogenの利用

Halogenの利用 続いて、GUIでBrainfuckを動かすことをやってみる。 GUIのフレームワークとして、ここではpurescript-halogenを使ってみる。 Halogenについてはまだ勉強中で、この記事は解説記事というより勉強記録である(いままでの記事もそうではあるのだが)。 % spago install halogen 雛形 src/Main.pursを以下のようにする。 ここのコードはほとんどHalogen Guideと同様。 関数名的におそらく、body要素を取得して、その中でcomponentを走らせるのだと思う。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 module Main where import Prelude import Effect (Effect) import Halogen.Aff (awaitBody, runHalogenAff) as HA import Halogen.VDom.Driver (runUI) import Component (component) main :: Effect Unit main = HA.runHalogenAff do body <- HA.awaitBody runUI component unit body componentはsrc/Component.pursで定義する。とりあえず雛形を作成。 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 module Component where import Prelude import Halogen as H import Halogen....

2021-07-09 · (updated 2021-07-09) · 12 min · 2530 words

PureScriptで作るBrainfuckインタプリタ 3/4 CUIでの可視化

動作の可視化 インタプリタ動作中における内部状態を可視化できると面白い。 そこで、インタプリタ動作中のログを出力できるような仕組みを作る。 ログは以下のタイミングで起こるようにする。 onStart: インタプリタが動作したときに起こる。 onState state: 各ステップで状態を取得したときに起こる。 onCmd cmd: 各ステップで命令を取得できたときに起こる。 onEnd: インタプリタが終了するときに起こる。 これらはイベントリスナのように、関数の形で指定する。 Logの作成 src/Brainfuck/Interp/Log.pursを作成。 以下のimport文を書く。 1 2 3 4 5 6 7 8 9 module Brainfuck.Interp.Log where import Prelude import Brainfuck.Interp (Interp) import Brainfuck.State (State) import Brainfuck.Command (Command) import Effect.Class (class MonadEffect, liftEffect) import Effect.Console (log) Logを定義。 1 2 3 4 5 6 newtype Log m = Log { onStart :: Interp m Unit , onState :: State -> Interp m Unit , onCmd :: Command -> Interp m Unit , onEnd :: Interp m Unit } 関連する関数を定義。...

2021-07-06 · (updated 2021-07-09) · 12 min · 2395 words

PureScriptで作るBrainfuckインタプリタ 2/4 CUIでの入出力

入出力用のストリーム作成 例えば出力だけ考えてみると、まず考えられるのは単純に、 logで出力することである。しかしlog以外の選択肢も考えられる。 logでコンソール出力するだけでなく、Webページのテキスト上で出力したり、テキストファイルに吐き出したりできるような汎用性が持たせられると良い。 そこで今回は、いわゆる「ストリームオブジェクト」のようなものを作って、そこから入出力を行うような設計にしてみる。 Streamの作成 src/Brainfuck/Interp/Stream.pursを作成。この後使うモジュールをインポート。 1 2 3 4 5 module Brainfuck.Interp.Stream where import Prelude import Brainfuck.Interp (Interp) Stream型を作成する。これは入出力を束ねた型になっている。 inputは、外部からの入力を1文字受け取る。 outputは、Charの値を外部に出力する。 1 2 3 4 newtype Stream = Stream { input :: Interp Char , output ::Char -> Interp Unit } Streamを通じてデータを読み書きする関数を作成。 1 2 3 4 5 6 7 read :: Stream -> Interp Char read (Stream { input }) = input write :: Char -> Stream -> Interp Unit write c (Stream { output }) = output c 1 2 3 4 5 6 defaultStream :: Stream defaultStream = Stream { input, output } where input = pure 'N' -- Not Implemented output _ = pure unit -- Not Implemented ‘....

2021-07-05 · (updated 2021-07-06) · 7 min · 1343 words