リモートワーク向けに最適なヘッドセットの選び方

リモートワーク歴がそれなりに長く、仕事でミーティングなど使うヘッドセットについては少し拘りポイントがあります。

無線より有線

無線だと電池切れの心配があるためです。 在宅であればすぐに充電できますが、カフェやコワーキングスペースなどではコンセントの差込口が1席に1〜2つ程度のことが少なからずあり、希少な存在です。

また、長時間のミーティングが続いたり、リモートワークが連日続いたり、そういうちょっと大変な状況ほど充電し忘れリスクが高まります。

それと、無線の方が有線より接続の手間があるように感じます。一度ペアリングしてしまえばいい感じに切り替えたりできるものもありますが、そうでない商品もわりとあるので、面倒くさいと思ってしまいます。

ノイズに強い

カフェやコワーキングスペースで仕事をすることがあるため、何かしらノイズ対策のあるものがいいと思っています。 後者はわりと静かなところが多いですが、前者はそれなりにがやがやしているところの方が多いですし、むしろ多少賑やかなカフェの方がこちらも気兼ねなく話せます。

ノイズ対策はマイク部分とイヤホン部分との両方に必要です。

マイク部分についてはmノイズキャンセリング機能があるか、または単一指向性であるとよい感じです。 また、最近はAIで高性能なノイズキャンセリング機能を実現しているものもあり、興味をそそられています。

イヤホン部分についてはノイズキャンセリング機能があるか、または遮音性の高いカナル型がよいと思います。 また、片耳のものや骨伝導のものは避けたいです。 Shokzの骨伝導は大好きなのですが、個人的に仕事用には選びません。

安価

安さは正義だと思っています。

そうなると必然的に無線より有線が有利で、この点は先述の有線を選ぶ理由とも関連しているといえます。 といっても、無線で安価なものもどんどん増えている印象です。安い無線の予備を複数個携帯するという方向性も実はアリなのかもしれません。

USBより4極ミニプラグ

PCやモバイル端末のUSB端子を塞ぎたくないためです。

イヤホンジャックの無いスマホで急遽ミーティングに参加する必要がある場合のみ、変換機器を挟むようにしています。 ダイソーで500円で売ってる「充電しながら使えるUSB TYPE-C変換ケーブル」がお気に入りです。

充電しながら使えるUSB TYPE-C変換ケーブルjp.daisonet.com

ちなみに、100均で売っているUSBと4極ミニプラグの変換プラグは、スマホで使えないものがあるので注意です。 これは、USBから出力されるデジタル信号を4極ミニプラグ向けのアナログ信号に変換するDACという部品が含まれていないものが該当します。 DACありのものを買うようにしましょう。

コンパクト

もしオーバーヘッド型なら、ヘッドバンドは折り畳めたり縮めたりできてほしいです。 こうなるとグッと選択肢が狭まります。折りたたみ可能なヘッドセットは希少なのです。 今はなきAKG K414Pのような名機がヘッドセット界にも誕生してほしいものです。

イヤホン型ならくるくると巻くだけなのでコンパクトですが、なにかしら巻くための小物があると便利かもしれません。

猫耳

これは不要です。

具体的な商品

これだけの条件を満たすような製品があるのかというと、あります。 外ではaudio-technicaさんのATH-202COMをメインで使っています。 どちらも素晴らしい製品です。継続して販売してほしいものです。

www.audio-technica.co.jp

https://www.sanwa.co.jp/product/syohin?code=MM-HS407BKwww.sanwa.co.jp

Go言語で日本時間を扱うときの罠

Go言語で日本時間を扱う方法をググると以下のようなコードをよく見かけます。

jst := time.FixedZone("Asia/Tokyo", 9*60*60)

このコードはある特定の場合にバグを引き起こす原因となるため避けるべきです。 どんな場合かというと、すばり夏時間が絡む場合です。

ja.wikipedia.org

日本に夏時間があったのは、戦後間もない1948年〜1951年のごく短期間です。 そもそも日本に夏時間があったこと自体を知らない人も多いので、これに起因するバグは原因の調査が難航しやすくなります。

ではどうすればいいのかというと、 time/tzdata に夏時間情報が含まれているのでインポートしておきましょう。

import (
    "time"
    _ "time/tzdata"
)

func main() {
    jst, err := time.LoadLocation("Asia/Tokyo")
    if err != nil {
        ...
    }
    ...
}

古いGoだとプラットフォームのtzdataを使っていたので、たとえばAlpineLinuxなどだと明示的にapk add tzdataする必要がありました。 今のGoは独自にtzdataを持つようになったので、プラットフォーム非依存になっています。

Git Aliasで引数を受け取る

Gitで引数を受け取ることのできるAliasの書き方があるようなので、紹介しておきます。

mikebarkas.dev

基本形は以下の通り。

[alias]
  echo = "!f() { echo ${1}; }; f"

このように~/.gitconfig記載すると、

$ git echo foo
foo

Aliasの先頭に!を付けるとシェルコマンドとして認識されるので(つけないとpullやcommitなど、gitコマンドのサブコマンドと認識されます)、つまり上記はシェル関数を定義して即時実行するという仕組みです。 考えてみればシンプルですが、これは物凄く応用範囲が広くて便利です。 たとえば、以下のような感じに使えます。

[alias]
  ls-repos = "!find . -type d -name .git | xargs dirname"
  for-all = "!f() { for DIR in $(git ls-repos); do git -C $DIR $@ & done; wait; }; f"

ls-reposでカレントディレクトリ下のすべてのローカルリポジトリを列挙するエイリアスです。 for-allは、このls-reposで列挙した各ローカルリポジトリでgitコマンドを実行します。 このときサブコマンドを引数として与えているので、任意の操作を行うことができます。

$ ls
repo-1 repo-2 repo-3
$ git for-all pull
Already up to date.
Already up to date.
Already up to date.

みたいな感じ。

個人的には、Go Workspaceで複数リポジトリを使用しているのでこれが便利です。

ちなみに以上はGit AliasのシェルがBashの場合です。Zshだとシンプルにecho = "(){ echo ${1} }"という感じに書けるとかなんとか。

NuxtJS + Sass(SCSS)でStylelint v14

Stylelint v14から破壊的変更が入り、Sassなどのルールはプラグイン化されました。 それに伴って、すでに導入済みの設定がある場合、いくつかの変更を加える必要があったので記録しておきます。

公式の移行ドキュメントは以下です。

https://stylelint.io/migration-guide/to-14/

結論を先に書くと、追加が必要な依存は以下です。

yarn add -D postcss postcss-scss
yarn add -D stylelint-config-standard-scss
yarn add -D postcss-html

で、stylelint.config.jsを以下のように修正します(元ファイルはプロジェクト次第なので、あくまで簡略版)。

 module.exports = {
-  extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
+  extends: ['stylelint-config-standard-scss', 'stylelint-config-prettier'],
   rules: {
     'selector-pseudo-element-no-unknown': [
       true,
      {
        ignorePseudoElements: ['v-deep'],
      },
     ],
   },
+  overrides: [
+    {
+      files: ['**/*.vue'],
+      customSyntax: 'postcss-html',
+    },
+  ],
 }

まずpostcssですが、これはSassとかLessを使う場合は基本的に必要となる模様。 SCSSを使いたいのでpostcss-scssも一緒に追加しています。

stylelint-config-standard-scss は、今回からプラグイン化されたSCSSのルールです。 インストールしたらstylelint.config.jsのextendsに追加します。 これは公式ドキュメント通り。

最後にpostcss-htmlは、<style>タグに挟まれた部分だけチェックするようにしてくれるものです。 NuxtJS (Vue.js)特有の事情として、*.vueファイル中のスタイルは<style>タグ内に書くため、これが必要になります。 *.scssファイルなどでは不要なので、stylelint.config.jsのoverridesで*.vueファイルにのみ適用されるよう設定します。

以上です!

Fedora 35にFlutterをインストール

前提

Android StudioをFlatpak経由でインストール済みの場合を想定しています。 FlatterはSnap経由でインストールするのが簡単そうなのですが、すでにFlatpakを使っており、これ以上パッケージマネージャーを増やしたくないし、このためだけに乗り換えるのもなんだかなあという人の参考になればと思います。

大筋は以下に従います。 docs.flutter.dev

依存関係のインストール

公式によるとClang, CMake, GTK development headers, Ninja build, pkg-configが要るとのことですが、pkg-configはデフォルトで入っているようなのでそれ以外をインストールします。

sudo dnf install ninja-build cmake clang gtk3-devel

Flutterのインストール

ホームにbin/というディレクトリを掘って、そこにgit cloneします。 どこでもいいのですが、普段から~/binに自作スクリプト類を色々と置いてるのでそこに同居させています。 全ユーザーが使うなら/opt/などがいいと思います。

mkdir ~/bin
cd ~/bin
git clone https://github.com/flutter/flutter.git

PATHを通します。 .bashrcか.bash_profileに以下を追記してください。

export PATH="$HOME/bin/flutter/bin:$PATH"
source ~/.bash_profile

flatter doctorが通るようにする

まずはAndroid Studioを立ち上げ、各種アップデートを完了しておいてください。

Android Studioが大人しくなったら、Flatpak経由で入れた場合のAndroid StudioのパスをFlatterに教えてあげます。

flutter config --android-studio-dir=/var/lib/flatpak/app/com.google.AndroidStudio/current/active/files/extra/android-studio/

つぎに、Android SDKコマンドライン ツールを入れます。 Androidのsdkmanagerコマンドを使えるようにするため、.bashrcか.bash_profileに以下を追記してPATHを通してください。

export PATH="$HOME/Android/Sdk/tools/bin:$PATH"
source ~/.bash_profile

今のsdkmanagerはJava8でないと動かないようなので、alternativesコマンドで切り替えておきます(Java8がインストールされていない場合は入れておいてください)。 以下のコマンドで使用するJavaのバージョンを選択できます。

sudo alternatives --config java

java --versionでJava8に切り替わってることを確認できたら、Android SDKコマンドラインツールのインストールを実行します。

sdkmanager --install "cmdline-tools;latest"

これでflutter doctorコマンドを実行して、全項目[✓]になればOKです!

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 2.6.0-12.0.pre.789, on Fedora Linux 35 (Workstation Edition) 5.14.18-300.fc35.x86_64, locale ja_JP.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Chrome - develop for the web
[✓] Android Studio
[✓] IntelliJ IDEA Community Edition (version 2021.2)
[✓] VS Code (version 1.62.3)
[✓] Connected device (1 available)

• No issues found!

Java 11に戻した上でflutter doctorしても通ったので、とりあえずこれでOKだと思います。

Fuzzy Containsについて

小ネタです。

かつてあいまい検索といえば、レーベンシュタイン距離などで語句同士の類似度合いを数値化して、域値で絞ったり類似度順に並べるのが普通だったように思います。

ja.wikipedia.org

ですが、数年くらい前からか、もっと簡単なあいまい検索をよく見かけるようになりました。 AtomやVS Code、GitHubのファイル検索なんかで使われているあれです。

なんて名前なのかな?と思っていたのですが、Fuzzy Containsとか呼ばれているようです。

とても単純なロジックなのでサクッと書けます。 JavaScriptだと以下のような感じ。

function fuzzyContains(query, target) {
  if (query.length > target.length) return false;
  for (let i = 0, j = 0, l = query.length; i < l; i++, j++) {
    j = target.indexOf(query[i], j);
    if (j === -1) return false;
  }
  return true;
}

結果は文字が順番通りに含まれているか否かという二値だけですが、場面によってはこれが類似度を使うよりも直感的で使いやすいように感じます。 気に入ったのでいろいろなところで使っていきたいと思います。

ホーナー法について

たいしたことないネタでもちょいちょい記事を書いてみることにします。今日はホーナー法について。

ホーナー法 - Wikipedia

www.ndl.go.jp

多項式を計算する際、乗法の回数を削減することができます。上記リンク先によると、19世紀からある方法のようです。

やり方はとてもシンプルです。以下のような多項式があるとします。

\displaystyle
p(x) = a_0 + a_1x+a_2x^{2}+ \cdots +a_nx^{n}

これを、次のように変形するだけです。

\displaystyle
p(x) = a_0 + x(a_1 + x(a_2 + \cdots x(a_{n-1} + a_n x)\cdots))

JavaScriptで実装すると、以下のような感じになります。

var horner = (coeffs = [], x) => coeffs.reduce((a, b) => a * x + b, 0);

もしくは、簡潔さより高速さということであれば、以下のような感じでしょうか。

var horner = (coeffs = [], x) => {
  var r = coeffs[0];
  for (let i = 1, l = coeffs.length; i < l; i++)
    r = r * x + coeffs[i];
  return r;
}

第一引数には、[a_n, a_{n-1},\cdots,a_0]の順に係数の配列を渡します。

実際のところ、べき乗の計算は効率的なアルゴリズムが知られているため、素直に展開形を実装するのに比べて、ホーナー法でそこまでの高速化は期待できません。 ただ、特に小数がある場合、計算精度の向上を望めます。

また、FMA (Fused Multiply-Add) をサポートしている環境では、更なる精度向上が期待できそうです。 例えばJuliaはfma()関数を呼び出すことで、CPUが対応していればFMAを使うことができます。

function horner(coeffs, x)
  r = coeffs[1]
  for i in 1:length(coeffs)
    r = fma(r, x, coeffs[i])
  end
  r
end

FMAについては、以下のブログ記事が参考になりました。

math-koshimizu.hatenablog.jp

ちなみに、JuliaについてはBase.Math中に@horner(x, p...)というマクロが予め定義されているようです。

github.com

以下のようにして呼び出すことができます。

julia> using Base.Math: @horner
julia> a0, a1, a2 = 0.123, 0.234, 0.345
julia> x = 0.999
julia> @horner x a0 a1 a2
0.701076345

とても簡単に使えるアルゴリズムなので、ぜひ活用したいです。

以下の本を参考に書きました。

[改訂新版]C言語による標準アルゴリズム事典 (Software Technology)

[改訂新版]C言語による標準アルゴリズム事典 (Software Technology)