2019年11月10日日曜日

sox equalizer

目的


soxのequalizerのヘルプに書かれている [q|o|h|k] の意味がわからないので、調べてみます。
$ sox --help-effect equalizer
sox:      SoX v14.4.2

Effect usage:

equalizer frequency width[q|o|h|k] gain
幅の単位であることは読み取れます。

調査に使ったコード


調査には https://git.code.sf.net/p/sox/code を利用しました。 コミットのハッシュ値は 2f6b3fec2dddfbb869a9f7de3110c9aaa31517c9 (Date: Wed Aug 1 23:45:59 2018 -0400) でした。

結果


hはHz、qはHzの逆数に操作する周波数を掛けた値であることがわかりました。また、oはオクターブっぽく、kはよくわからないこともわかりました。

記載箇所


equalizerは src/biquads.c に記述されています。

オプションの解析部分を追っていくと、

q = width_Q
o = width_bw_oct
h = width_bw_Hz
k = width_bw_kHz
であることがわかります。

このファイル内に、これらを使っている箇所があります。

static int start(sox_effect_t * effp)
{
  ...
  if (p->width) switch (p->width_type) {
    case width_slope:
      alpha = sin(w0)/2 * sqrt((A + 1/A)*(1/p->width - 1) + 2);
      break;

    case width_Q:
      alpha = sin(w0)/(2*p->width);
      break;

    case width_bw_oct:
      alpha = sin(w0)*sinh(log(2.)/2 * p->width * w0/sin(w0));
      break;

    case width_bw_Hz:
      alpha = sin(w0)/(2*p->fc/p->width);
      break;

    case width_bw_kHz: assert(0); /* Shouldn't get here */

    case width_bw_old:
      alpha = tan(M_PI * p->width / effp->in_signal.rate);
      break;
  }
  ...
width_Qはwidth_bw_Hzとは逆に動いているので、qを大きくすると幅が狭くなるようです。

width_bw_kHzについては、assert(0)では止まらないので、はwidth_bw_old扱いになるようです。 全然kHzではありませんね。

参考までに、pの型はbiquad_tで、定義は、src/biquad.h より、

typedef struct {
  double gain;             /* For EQ filters */
  double fc;               /* Centre/corner/cutoff frequency */
  double width;            /* Filter width; interpreted as per width_type */
  width_t width_type;

  filter_t filter_type;

  double b0, b1, b2;       /* Filter coefficients */
  double a0, a1, a2;       /* Filter coefficients */

  sox_sample_t i1, i2;     /* Filter memory */
  double      o1, o2;      /* Filter memory */
} biquad_t;
です。

2019年8月31日土曜日

Debian10のPCのルータ化

目的


Debian10 (Buster) をインストールしたPCをルータにします。

インターネット側のネットワークインターフェイスenxと、内部ネットワーク側のネットワークインターフェイスeniがあるとして説明します。

[内部PC1]┬(eni)[ルータ化するPC](enx)─[インターネット]
[内部PC2]┘
なお、試行錯誤したあとにまとめているため、記載通りでは動かない可能性があります。

おおまかな手順


おおまかな作業手順は次のとおりです。
  • IPアドレスの固定
  • isc-dhcp-server (DHCPサーバ)のインストールと設定
  • nftables (NAT用)のインストールと設定
  • bind9 (DNSサーバ)のインストールと設定
以下の作業ではすべてルートで行うか、sudoで実行してください。

IPアドレスの固定


Debian10ではNetworkManagerがデフォルトで動作しています。そのため、nmcliを使って、eniのIPアドレスの固定します。 残念なことにGUIを使った設定では、いずれか1つのネットワークインターフェイスしか有効にできないようです。

nmcliの解説はhttps://go-journey.club/archives/4124が参考になります。

有線LANの場合、作業の開始前にLANケーブルを接続しておくことをお薦めします。 接続がないとSTATEに利用不可と表示され、設定した結果を確認できなくなります。

最初に、ネットワークインターフェイスをNetworkManagerから見えるようにします。

$ nmcli connection add type ethernet ifname eni con-name eni
次に、eniのIPアドレスを指定します。
$ nmcli connection modify eni ipv4.method manual ipv4.addresses 10.0.0.1/27
しばらくすると、IPアドレスが固定され、ネットワーク接続が完了します。

ネットワークの状態は

$ nmcli device
で確認できます。

DHCPサーバの設定


isc-dhcp-serverをインストールします。
$ apt install isc-dhcp-server
isc-dhcl-serverの設定ファイルは /etc/dhcp/dhcpd.conf にあります。

そこに次の内容を追記します。

subnet 10.0.0.0 netmask 255.255.255.224 {
  range 10.0.0.10 10.0.0.20;
  option routers 10.0.0.1;
  option domain-name-servers 10.0.0.1;
}
IPアドレスは適宜変更してください。この設定で配布されるIPアドレスは、10.0.0.10〜10.0.0.20の範囲です。

最後に、DHCPサービスを再起動します。

$ systemctl restart isc-dhcp-server
これで内部PCにIPアドレスが配布されます。

NATの設定


ルータとして動作するようにするために、まず、 /etc/sysctl.conf に
  net.ipv4.ip_forward=1
を追記します。コメントアウトされた状態で記載されているので、コメントを外すだけです。

この設定を次のコマンドを実行することで有効にします。

$ sysctl --system
有効になっているかは
$ cat /proc/sys/net/ipv4/ip_forward
で確認できます。出力が1になっていれば、OKです。

次に、NATを有効にします。NATはファイアウォールの機能の一部ですので、Debian10から標準となったnftablesを用います。

$ apt install nftables
でインストールし、/etc/nftables.conf に次の内容を追加します。
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 100;
    oifname "enx" masquerade
  }
}
追記できればサービスを有効化し、実行します。
$ systemctl enable nftables.service
$ systemctl restart nftables
クライアントから8.8.8.8にpingが通るようになっていれば成功です。

DNSサーバの設定


BIND9をインストールするだけです。
$ apt install bind9
https://www.clear-code.com/blog/2010/11/19.htmlが参考になります。

もし、クライアントのブラウザからドメイン名を使ったアクセスができない場合は、

$ systemctl restart isc-dhcp-server
で、DHCPサービスを再起動してみてください。

以上で、ルータが完成です。セキュリティー関連の設定は別途実施してください。

2019年8月25日日曜日

Debian10でのデスクトップ環境の変更

Debian10は、インストール時にデスクトップ環境を複数インストールすることができます。

例えば、GNOMEとCinnamonの2つをインストールすると、ログイン時にどちらの環境でログインするかを選択することができます。 この2つをインストールしておくと、デフォルトではGNOMEが選択されるようになっています。

デスクトップ環境をGNOMEからCinnamonに変更するには、ログイン画面のパスワード欄の下にある、小さいギアのアイコンのボタンを押します。 すると、選択できるデスクトップ環境の一覧が表示されるので、使いたい環境を選択します。

その後、ログインすると、選択した環境で作業できるようになります。

ボタンの場所は記事の図を参考にしてください。
https://computingforgeeks.com/how-to-install-cinnamon-desktop-en\ vironment-on-debian/
具体的には、 install-cinnamon-deb10-03.pngです。

Debian10でWacomタブレットを使う

現象


Debian10を標準でインストールし、Wacomのタブレット(CTH-480)をつなげ、ペンで操作していると、マウスカーソルが頻繁に消失します。 また、タブレット操作とペン操作のそれぞれに対してマウスカーソルが表示されるという症状も出ていました。

原因


Waylandがタブレットを正しく処理できていないことが原因のようです。

解決策


/etc/gdm3/daemon.conf でコメントアウトされている次の行のコメントを外して有効にします。
WaylandEnable=false
その後、再起動すると、Waylandの代わりに従来のXが使われるようになります。

Xは正しくペンタブレットを処理できるようで、マウスカーソルが消えたり2つになったりする現象はなくなりました。

WaylandをOFFにする方法は、
https://linuxfan.info/ubuntu-gdm-wayland-false
を参考にしました。

2019年7月27日土曜日

電気いらずの脱塩装置

太陽光だけで海水を真水にできる装置が発表されました。

https://www.monash.edu/news/articles/water-solutions-without-a-grain-of-salt
https://www.newsweekjapan.jp/stories/world/2019/07/post-12625.php

円盤状の濾紙の中央に水を吸い上げて、太陽光で蒸発させます。
これを集めれば真水になりますね。

水に溶けていた塩は円盤の外側へと排出されます。

もこもこ塩が湧き出てくる動画が面白い。
https://youtu.be/OGZVhcQ33MQ

2019年5月27日月曜日

J-PlatPat が更新

J-PlatPatが更新されて、いい感じに使いにくくなったので、とりあえずの検索をするときの使い方をメモしておきます。

投稿日時点の使い方なので、今後使い方が変わっていく可能性はあります。
(そもそもずいぶん前に更新されていたのかもしれません)

ざっくり調べたいときは、全文検索かつキーワードをANDでつなげたいことが多いです。
Googleの検索と同じですね。

選択入力


「選択入力」を使うときは、「検索項目」を「全文」に設定して、キーワードに1単語ずつ入力していきます。1単語ずつ!、です。複数単語を入れるとORになります。
残念なことに指定したい単語の数が多いと、この作業はとても手間がかかるので、「論理式入力」を使ったほうが簡単です。

論理式入力


論理式入力で全文検索かつANDで単語をつなげるには、例えば
機械学習/TX*分散処理/TX*プロトコル/TX
または、
(機械学習*分散処理*プロトコル)/TX
のように指定します。*がAND式で、/TXが全文を対象にする式(構造タグ)です。

使える演算子について


ヘルプには記載されているのですが、見たら分かるであろう画面の使い方が記載されている部分が多く、見つけるのに時間がかかったので、ここにURLを貼っておきます。

[条件式一覧]
https://www.j-platpat.inpit.go.jp/help/ja/p01/arithmetic.html
の「使用できる演算子について」を開くと読めます。簡単に書いておくと、

* AND
+ OR
- NOT
[ ] 演算順位の変更(+と-を*より強くするときなどに使う)
( ) /以降をまとめる

例:

('Liquor'*['Wine'-'Japanese beer'])/TX

[構造タグ一覧]
https://www.j-platpat.inpit.go.jp/help/ja/p01/p0101.html#9994

使用頻度が高そうなものをピックアップしておきます。
TX 全文
AB 要約/抄録
CL 請求の範囲
FI FI
FT Fターム
IP IPC

でしょうか。

文献内検索


さて、そうして見つけた文献を表示して、ブラウザの検索機能で当該箇所を探そうとすると、全文が表示されていないため、全文検索ができません。そこで、「要約」「請求の範囲」「詳細な説明」を1つずつ開いておきます。幸いにも、次の文献を表示したときにまた当該項目が閉じられてしまうことはないので、多少はましでしょうか。サーバーの負荷を下げたい一心で設計したんでしょう。手間がかかってしかたがないですね。


また、文献サイズが大きいと、一度に表示できずに分割されてしまいます。
そのため、ブラウザの検索機能を使って全文を検索できません。
そういった場合は、仕方がないので、
- pdf出力をする
- Google patentで検索する
にしましょう。

そもそも最初からGoogle patentでいいのかもしれませんね。

2019年2月3日日曜日

wavの簡易表示

端末でwavファイルの中身を簡易表示するスクリプトを作ってみました。
https://bitbucket.org/bluewidz/asciiwave/src/default/aw
soxが必要です。

実行例です。

$ ./aw a.wav | head -n5
0.100s  18893   12375   18893   12375   18893   12375
0.200s  10841   6235    10841   6235    10841   6235
0.300s  8328    4031    8328    4031    8328    4031
0.400s  7479    3369    7479    3369    7479    3369
0.500s  6779    3056    6779    3056    6779    3056
0.100sの列は、0s-0.1sの間のサンプル値の絶対値の最大値を表示しています。
列はチャンネルを表しています。一番左が1チャネル目です。6列あるので、このファイルは6チャネル分のデータが含まれていることになります。

スケールを変更する場合は、1行にまとめるサンプル数を直接指定します。
$ ./aw -s 480 a.wav | head -n5
0.010s  0       0       0       0       0       0
0.020s  0       0       0       0       0       0
0.030s  0       0       0       0       0       0
0.040s  0       0       0       0       0       0
0.050s  39      25      39      25      39      25

2019年2月2日土曜日

ZeroMQでソケット通信

はじめに


Python3 + ZeroMQでソケット通信を試してみます。

PythonでZeroMQを使うためのpyzmqのドキュメントは、
https://pyzmq.readthedocs.io/en/latest/
https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/index.html
が、ZeroMQそのものの説明は
http://zguide.zeromq.org/page:all
が参考になります。

次の4パターン

  • Pair (Exclusive pair)
  • Client/Server (Request-reply)
  • Publish/Subscribe (Pub-sub)
  • Push/Pull (Pipeline)
が使えるようです。今回は、Publish/Subscribeで試します。せっかくなので、送受信にかかる時間も測定してみます。

コード


Publisher側のコードです。socket.send_pyobj でpythonのオブジェクトをそのまま渡すだけです。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import zmq
import time
import numpy as np

context = zmq.Context.instance()
socket = context.socket(zmq.PUB)
socket.bind("ipc://aaa")

w = np.ones(160) # numpy array to be sent
while True:
    t = time.perf_counter()
    socket.send_pyobj([t, w])
    print(t)
    time.sleep(1)

次に、Subscriber側のコードです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import zmq
import time

context = zmq.Context.instance()
socket = context.socket(zmq.SUB)
socket.connect("ipc://aaa")
socket.subscribe('') # Recieve all topics

while True:
    start, w = socket.recv_pyobj()
    end = time.perf_counter()
    print("{0} ms".format((end-start)*1000.0))
pythonオブジェクトの送信から受信までの時間をms単位で出力するようにしています。

実行結果


実行は、端末を2つ立ち上げて、上記のコードをpythonで実行するだけです。

実行してみると、Subscriber側では、
115.46662700129673 ms
0.5929949984420091 ms
0.9222489970852621 ms
0.7364909979514778 ms
0.5779260027338751 ms
0.5179920044611208 ms
0.5140290013514459 ms
0.5147350020706654 ms
0.5380119982874021 ms
0.5411919992184266 ms
0.5420840025180951 ms
0.5289019973133691 ms
0.8248919984907843 ms
0.9655120011302643 ms
0.7765349946566857 ms
0.6397230026777834 ms
0.7840489997761324 ms
1.0322410016669892 ms
0.7769410003675148 ms
0.774603002355434 ms
0.7632400011061691 ms
0.7989099976839498 ms
0.8185699989553541 ms
0.8329580014105886 ms
と出力されました。おおむね1ms以下で送信できているようです。ただ通信したいだけの用途なら十分な速さですね。

送信データ量を増やす


numpy arrayを作るところを1000倍してみたところ、
w = np.ones(160000)
さすがに3ms前後かかるようになりました。
118.689604998508 ms
6.79611799569102 ms
3.675059000670444 ms
3.75746200006688 ms
3.62611300079152 ms
3.6894719960400835 ms
2.672021997568663 ms
3.772675001528114 ms
3.641210001660511 ms
3.5925789998145774 ms
3.0622690028394572 ms

通信をtcpに変更


さらに、通信を次のようにtcpに変更してみました。
[Publisher]
socket.bind("tcp://*:5556")

[Subscriber]
socket.connect("tcp://localhost:5556")
すると、
117.72498200298287 ms
6.720707002386916 ms
4.039794999698643 ms
3.9917790054460056 ms
4.0376230026595294 ms
3.933735999453347 ms
3.9876959999674 ms
4.071578005095944 ms
4.004092996183317 ms
となりました。ipcよりtcpのほうが若干遅いようです。