kumak1’s blog

kumak1のイラストや技術ログ

バ美肉してみたいから iPhone の GarageBand でボイチェンを試してみる

はじめに

2018年の楽しい地獄コンテンツ、 バーチャル美少女受肉おじさん 。皆さん把握してますか。 色々察して「アッ」ってなった人はブラウザバックしよう。

一過性のブームではないと思うの

皆、思い思いに活用している。TwitterInstagram でアイコンを通して文字のコミュニケーションを取るように、3Dアバターを通して音声や表情のコミュニケーションが当然になる未来は近い・・はず。

実は美少女声は必須じゃない・・が

声を変えるのはバ美肉に必須ではない。( 国王 とか、まきりむ とか) けれど、手っ取り早く「変身した私」を演出できるので、ボイチェン適正があるかスパッと確認してみるとよさそう。 魔王も「高い機材を買っても大幅に声質が変わるわけではない。手持ちの機材で適合者かどうか、まずは確認するといい」って趣旨のこと言ってた・・はず。(違ってたらごめんなさい)ので下記方法でスパッと確認してみよう。

機材について

恋声について

Windows PC + 恋声 がなにかとメジャーで、解説しているブログも多い。これはもう 先人の説明 で十分に思う。 この方法で私が辛いな、と感じたのは、恋声に入力する声は高ければ高いほど良いこと。 (低い声を無理やり高く変換すると、人間の声じゃなくて、明らかに変換かけた音になってしまう) 私はそこそこ声低めな人なので(下にサンプルボイス有)メラニー法などでだいぶ声を変えてあげる必要が出てきて、長時間の会話はつらい。 「メラニー法で長時間話せるようボイトレしなきゃか・・」とモニョモニョしてたところ、有識者から「LogicPro, GarageBand はいいぞ・・」という言葉をいただいた・・

じゃあ GarageBand

試しに MacGarageBand を用い「気持ち高め」程度の声を入力してみたのだけど、あまり調整しなくで割と自然な声に変換されて驚いた。(効果には個人差があります) 「より手軽に試せたらなぁ(Mac 持ってない人も多い)」と思っておもむろに iPhone 版の GarageBand を起動してみたのだけど、ほぼ同じ操作で同じ効果を得られた、すごい。お家じゃなくてもすぐ確認できるので便利だな?家族と暮らしてる人は特に。 ということで iPhone6 と付属のイヤフォンマイクを使った設定・確認方法を以下で解説します。

設定方法

まずは iPhone に付属のイヤフォンマイクを指しておく。その後 GarageBand を起動して、以下の手順に従って操作し、初期設定しよう。

プロジェクトの初期設定
  • プロジェクトの新規作成
    • f:id:kumak1:20180927132940p:plain
      右上の + を押下
  • TRACK の新規作成
    • f:id:kumak1:20180927133056j:plain
      ボイスを選択
  • モニタ の設定
    • f:id:kumak1:20180927133658j:plain
      プラグのアイコンを押下
    • f:id:kumak1:20180927133834j:plain
      モニタをオンにする。その後 '完了' を押下

これで初期設定は完了。イヤホンから周囲の音や、自分の声が出力されていれば設定OK。

プラグイン設定のひと通りの流れ
  • f:id:kumak1:20180927204234j:plain
    歯車を押してからトラックコントロールを押下
  • f:id:kumak1:20180927204243j:plain
    プラグインとEQの右の > から詳細を開く
  • f:id:kumak1:20180927204308j:plain
    編集を押下
  • f:id:kumak1:20180927204318j:plain
    プラグインのセット可能数は上限があるので不要なものを削除
  • f:id:kumak1:20180927204342j:plain
    + を押下してプラグイン追加
  • f:id:kumak1:20180927204356j:plain
    Vocal Transformer がボイチェンなので押下
  • f:id:kumak1:20180927204402j:plain
    Pitch Formant を自分の声に合わせて設定する
プラグインの設定

私が(暫定的に)設定したプラグインは下記の順番で登録しました。 VOICE TRANSFORMER 以外の狙いはすべて機械音を減らすことです。

  • COMPRESSOR
    • マイクに入力された大きすぎる音を調整するのが目的。
  • CHANNEL EQ
    • ローカットを設定。マイクのノイズ削減が目的。
  • VOICE TRANSFORMER
    • ボイスチェンジ!私は Pitch +8 Formant +2 くらいに設定してます
  • CHORUS
    • 声からちょっと高めの周波数帯で音を重ねることで、機械音っぽさを抑えます
  • CHANNEL EQ
    • 3000Hz 以上を抑えることで、機械音・ノイズっぽさを抑えます
  • TRACK REVERB
    • 時系列で音を重ねることで、機械音っぽさを抑えます

試聴してみよう

地声

ボイチェン

ボイチェン用の声(ボイチェン前)

ということで、地声が低めの人でも、気持ち高めで丸い声を意識して出してみたら意外と大丈夫、のはず。 (設定値等々はやっつけなので、設定値詰めてメス落ちすれば・・) GrageBand のサンプルプロジェクトも用意しときました。ナニカのお役に立てください。

http://kumak1.sub.jp/audio/TransSample.zip

より高みを目指すために

ここからはちょっと専門的になってしまうが、FFT解析を用いて「理想とする声」と「ボイチェン後の自分の声」を比較してみよう。 FFT解析を無料で行うには 「SoundEngine」無料の音声ファイル編集ソフト - 窓の杜「Audacity」フリーの波形編集ソフト - 窓の杜 が鉄板。 相違する音の成分を補うように、出す声を変えてみたり、プラグインを調整すれば、より理想に近くなっていくでしょう。 本職の人が解説しているブログもあるので、参考にするとよさそう。

purureko.com

私もこれからアップデートを重ねて行こうと思う。

まとめ

ということで(?)、バーチャルアバター全国普及率50%となる未来はそう遠くはない。備えよう。 この後の作業は受肉すればよろしい。 2DCGが描ける人は Live 2D + FaceRig の解説をしている、りむとまきチャンネルを参考に作成しよう。

www.youtube.com

3DCGができる人は、いつもどおりです。

ちょっとした野望

バ美肉 Tech Meeting みたいな勉強会してみたい

Fabric2 へ移行した際の雑Tips

更新履歴

  • 2018/08/20 コマンドのエラーを無視して後続処理する方法を追記
  • 2018/10/24 接続先でシェルを使いたい場合のオプションを追記

はじめに

Python 製タスクランナーの Fabric 2 が公開され、Macbrew でもこのバージョンになりました。 Fabric 1 の記法では動かなくて私は阿鼻叫喚したのですが、みなさんはいかがでしょうか? まだまだ日本語ドキュメントも少ない(ほぼない?)し、移行事例があまりなかったので、雑なものですがメモを残しておきます。

なお、ここでは英語ドキュメントで大々的に示してるメイン機能(ConnectionGroup など)の使い方を説明するものではなく 「あれ、v1 でやってたこの処理、どうやってやるんだろ?」という細かなものを中心をしています。

Fabric 1 と 2 って、ゆうてそんなに変わらんのやろ?

めっちゃ変わる。違うフレームワーク触ってる感覚

  • v1
    • 単一ライブラリで構成された、シェル便利実行君
  • v2
    • Invoke (タスクランナー)の上に、Fabric な拡張(サーバ接続設定等)を足したもの

お約束

task の引数の渡し方について

v1 では fab task:foo=bar,hoge=fuga のように引数を渡していたが、 v2 では fab task --foo=bar --hoge=fuga渡すようになったアノテーションで動作を様々に制御可能なので確認しておこう。

task には connection を渡す引数が必須

v1 では特に必要なかった。 v2 は接続情報の引数(以下の c )を必ず記載する必要がある。 task 内でホスト指定しない場合は fab -H host sample-function みたいにオプションで指定が必要になる。

from fabric import Connection
from invoke import task, Exit

@task
def sample_function(c):
    c.run('echo Hello World')

task をローカル実行のみしたい場合

v1 の local() コマンドはもういない。 v2 では run ライブラリを import し、connection を経由せずに実行すればOK

from invoke import task, Exit, run

@task
def sample_function(c):
    run('echo Hello World')

task のカレントディレクトリを変えたい

fabric 1 で存在した cd lcd などは オミットされた ので run("cd path && command") といった感じで実行しましょう・・

接続情報を ssh_config で管理したい

v1 では env.ssh_config_path="path/to/ssh_config" で指定できるが、 v2 では Config.ssh_config_path='path/to/ssh_config' で指定する。

python のコード で色々と動的に変更できるが、やはり扱い慣れた & 流用できる方法で proxy 設定などできると安心感が増すね。

from fabric import Connection, Config

Config.ssh_config_path = 'path/to/ssh_config'

コマンドの実行結果をうまく扱いたい

実行コマンド自体も表示したい

v1 で local() or run() する際、デフォルトで表示されてたが、 v2 の run() では、実行結果のみ stdout されるようになったのでオプション指定する必要がある。

from invoke import task, Exit, run

@task
def sample_function(c):
    run('echo Hello World')
% fab sample-function
Hello World

echo=True オプションを追加すれば、実行コマンド自体も表示される

from invoke import task, Exit, run

@task
def sample_function(c):
    run('echo Hello World', echo=True)
% fab sample-function
echo Hello World
Hello World

コマンドの実行結果を変数に格納したい

v1 では run()capture=True オプションを指定すれば取得できたが、 v2 では run() の返値は 複数の要素を持ったオブジェクト なので、適切に抽出してやる。

@task
def sample_function(c):
    result = run('echo Hello World').stdout.splitlines()[-1]
    print result + " foo"
% fab sample-function
Hello World
Hello World foo

追記 2018/08/20

コマンドのエラーを無視して後続処理を実行したい

v1 では run()warn_only=True オプションを指定すればエラーで中断しないが、 v2 では run()warn=True オプションを指定する

追記 2018/10/24

接続先でシェルを使いたい

v1 では run('/bin/bash') した場合は仮想コンソールが自動で立ち上がるが、 v2 では run()pty=True オプションを指定する

run('cd path/to/yaml docker-compose run CONTAINER_NAME /bin/bash', pty=True)

こんなときに便利

参考文献

Unity の Shader をそこそこ書けるようになるまでやったこと

2017年末の現状

Unity の3Dを触り始めて約1年。そこそこちゃんとした Shader が書けるようになってきました。 レンダリングサンプルはこんな感じ。

全編スクラッチしており、Normal Map や Matcap の設定はもちろん、アーティスティックな光や影の色を設定で作れるようになっています。

なんでまとめ記事書くの?

年末なので振り返り。 あと、よくゲーム開発系の話をする、同僚の いも@EFB~相手は死ぬ~ (@adarapata) | Twitter さんに 「ところでシェーダ書くのにどの辺を調べました?」と聞かれ、返答ながなが書いたら これコンテンツになるやつじゃん って気づいたため。

もともと持ってた技術

  • 情報系大学卒
    • CG技術系の基礎知識あり
    • 認知化学とかもやってた
  • 現職 web エンジニア
  • 色彩検定2級もってる程度の色知識
  • 趣味で絵を嗜む程度の Photoshop 知識

やったこと

  1. WebGL を 用いて Shader を用いてできることの全体像を掴む
    • wgld.org
    • 2016年 週3 ランチでハンズオンしつつ読み進めた
    • これだけで丸1年かかって2017年になってしまった・・
  2. Unity の全体像を掴む
  3. Unity の Shader 処理の全体像を掴む
    • esprog.hatenablog.com
    • Unity で Shader を扱う際は ShaderLab という、 Cg/HLSL (一般的な Shader 言語) をラップしたものを使う
    • Unity の用意したライブラリやら方言やらに慣れなきゃ作れない(SQLとかにも通じるものがある)
  4. やりたい事別の Shader の処理を理解する
    • esprog.hatenablog.com
    • alfa.hatenablog.jp
    • Surface Shader(コードをそんなに書かなくてもプリセットでそこそこ綺麗に出力) を、スクラッチで書いた場合」を見比べながら理解する。
    • 私が表現したいものは Unity が用意したものでは実現できないので、色々自作できるように知識をつける。
    • たとえば、光源の位置から影となる箇所を算出するなど、色々ある
  5. Standard Shader を読み解く
    • unity3d.com
    • あとは、ユニティちゃんシェーダーとか。
    • Web フレームワークとか OSS とかでもそうなんだけど、詳細知りたいなら公式の実装を見る事のが一番!
    • 逆に、公式が使っていない(サンプル公開していない)機能を使うのは危険だよね。いつオミットされてもおかしくない。
  6. 実際に Shader を書いて見る
    • ここは 4. 5. を行き来しながら進めてる。
    • イデアと関連付け能力の見せ所
    • 数学的な知識があると、より表現の幅が広がる〜〜と実感している

まとめ

まずは全体像をみて脳内に目次を作る。次に実装・資料確認を繰り返し、細かい所のナレッジを溜めていった。 web ほど流行り廃りは早くない世界なので、どっしりと落ち着いて学習を進めていける。 こういった再利用可能な描画技術の蓄積は、表現の豊かさに直結するので、気になったアナタもぜひこの沼に浸かりましょう。

Unity の SSAA アセット2つを比べてみた

SSAA とは

アンチエイリアスの技法のうちのひとつです。 Unity で現在よく使われているのが、SSAA と FXAA ですね。

そもそもアンチエイリアスってなんやねんって方はこちらを。

docs.unity3d.com

計算方法にどんな違いがあるか気になる方はこちらを参照するとなんとなくわかるでしょう。

ascii.jp

要は見た目をなんだかいい感じにしてくれるやつです。

SSAA をなんでえらんだの

別に「こっちが絶対に良い、完全上位互換だ!」みたいなのはありません。 作りたい画絵によって適した技術を使う必要があるだけです。 んまぁ、SSAA と FXAA の比較があるので、バーをスライドして比較してみたらわかりやすいかと。

GeForce.com Rise of the Tomb Raider Anti-Aliasing Interactive Comparison: SSAA 4x vs. FXAA - Example #001

SSAA : 木の枝といった、細い線を綺麗に映したい際に効果を発揮。 FXAA : 髪についた雪といった、明暗はっきりした箇所がよりナチュラル。

で、今回なぜ SSAA を選んだのかというと、アニメっぽい表現(線画があってフラット)を3Dモデルで表現して見たいからですね。http://ascii.jp/elem/000/000/746/746002

アセットについて

Unity のアセットストアには良さそうなのが2つあったので試して見ます。 イイね! 的なものは、古くから公開されていることもあり、Super Sampling SSAA が大差をつけて勝っています。

結論からいうと、 Super Sampling SSAA よりも MadGoat SSAA の方が優れていました。。 処理負荷についてはサンプルで利用した Scene が軽量・SSAOなど他高負荷処理と組み合わせていないので、厳密にベンチマークはとれなかった。。 のですが、わかりやすい課題点が見えたので調査を終えてしまいました。

問題1 GUIレンダリングがズレる

テスト用 Scene として用いたのは、Rewired という入力管理アセットのサンプル Scene CustomControllersTouch です。

ノーマル f:id:kumak1:20170530010403p:plain

Super Sampling SSAA f:id:kumak1:20170530010459p:plain

MadGoat SSAA f:id:kumak1:20170530010542p:plain

なんやらおかしな感じになっている

問題点2 エコシステムが・・

Super Sampling SSAA の最終更新日は 2016/2/29、公式フォーラム上でもバグ報告があがるものの、対応される気配はありません・・ (MadGoat SSAA をすすめる記述さえある・・)

https://forum.unity3d.com/threads/released-flowfire-super-sampling-ssaa-visually-best-anti-aliasing.332628/page-5

MadGoat SSAA の最終更新日は 2017/5/16、作者も(まだ?)意欲的で交流がすすんでいます。Unity の次期バージョン 2017 もサポートが明言されているのは嬉しい。

https://forum.unity3d.com/threads/released-madgoat-ssaa-and-resolution-scaling.462860/

問題点3 Unity 5.6.1 で動作しない

なぜか Unity 2017 β では動いていますが、色々アヤシイ・・

結論

私は MadGoat SSAA を使っていこう

VPS(ConoHa)を docker-machine で操作する

雑なメモ

ここ最近、webアプリの開発環境もリモートサーバで構築して動作確認してしまっている。

https://github.com/direnv/direnv で以下のように環境変数を登録してしまえば、ローカル感覚で(要いんたーねっとだが)扱えるので便利。 .envrc の記述は以下の通り。 ConoHa の設定のテナントIDとか、設定は自分好みにのに当てはめて利用してください。

# ConoHa の設定
export OS_TENANT_NAME=foo
export OS_TENANT_ID=foo
export OS_USERNAME=foo
export OS_PASSWORD=foo
export OS_AUTH_URL=https://identity.tyo1.conoha.io/v2.0

## ConoHa のコンテナ設定
export OS_FLAVOR_NAME=g-1gb
export OS_IMAGE_NAME=vmi-ubuntu-16.04-amd64

# Docker の設定
export COMPOSE_PROJECT_NAME=foo
export COMPOSE_FILE=docker/docker-compose.yml
export MACHINE_DRIVER=openstack
eval "$(docker-machine env $COMPOSE_PROJECT_NAME)"

設定完了後は .envrc を読み込んだディレクトリ上で以下コマンドを実行すればホスト作成してくれる。

docker-machine create $COMPOSE_PROJECT_NAME

あとは docker exec なり docker-compose で煮るなり焼くなり

好きなキーボードを使い続けるためにキーボード作り始めた

これは pepabo Advent Calendar 2016 - Qiita 11日目の記事です。 昨日はいつも隣の席で頑張っている yinm さんの 社会人生活をふりかえります - 楽しいだけで十分です でした。

はじめに

Amazon Dash Button が日本で開始されたり、ペパボのデザイナさんが 自宅の照明を点けたり消したりできるWebサービスを公開 していたり、いよいよIoTが特別なものではなく、身近なものになってきましたね。 「わたしだってソフトだけじゃなくてハードもエンジニアリングしたい!けど、いんたぁねっと使うの敷居高い・・」ので、まずは簡単な組み込み機器を作ってみようと思いました。

せっかくなので普段使える物を・・ということで、エンジニアらしくキーボードを作ってみます。静電容量方式の打ち心地が好みのため、仕事では REALFORCE104UG-HiPro を利用しています。が、 周りを見渡すElgo DoxKINESIS を使ってる人がいます。うぅむ・・親指で打鍵できるの便利そう・・。なので作ってみよう!

つかったもの

  • Pro Micro
    • Arduino Micro互換機
    • 500円程度で購入できてお財布に非常に優しい(Arduino Micro は3000円ほど)
  • Arduino UNO
    • AVR ライターとして
    • 3000円程度で購入できますが、部屋に転がっていたので有効活用
  • CHERRY メカニカル MXスイッチ 赤軸 + キートップ
    • キーボードのメインとなる機器
    • 安いタクトスイッチなどでもいいのですが、なんとなく拘ってみました
    • 2000円程度で揃いました
  • アルミ板
    • アルミ板自体は500円、加工代で3000円しました・・
    • 自分で加工するのがベストかもしれない

殆ど Amazon で手に入りますが、アルミ板を東急ハンズで購入、スイッチとキートップJW system から購入しました。キートップはベースとなる部分と透明なカバーで構成されていて、中にシールや紙を挟むことで好きな印字に変更できます。 Pro Micro は一昔前の USB メモリよりも小さく、初めてみたときは感動ものでした・・

f:id:kumak1:20161210212940j:plain

Pro Micro へ気軽に書き込みをできるようにする

キーボードを簡単に作るために、 Pro Micro を利用します。 Pro Micro はマイコンが1つのみで、プログラムの書き込みをした後、ずっとUSB機器として動作するため今回の用途にぴったりです。 (しかも、キーボード用のライブラリも公式で提供されているため、至れり尽くせり) 反面、プログラムの書き込みを何回も行いたい場合は面倒な操作(RSTとGNDを短絡させて8秒以内に云々・・)が必要になってしまいます。 そこで Arduino UNO を書き込み装置(AVR ライター)にしてしまい、Pro Micro へ Arduino Micro のブートローダを書き込むことで、プログラムの書き込みと実行がスムーズに行えるようにしてしまいます。 (Arduino Micro のブートローダを書き換えたら、Arduino IDE がよしなにしてくれるため、追加で書き込み放題となります)

Arduino UNO を AVR ライター化

MacArduino IDE を起動し、Arduino UNO と USB ケーブルをつないで以下画像の通り、 ボード: "Arduino/Genuino Uno" シリアルポート: "Arduino/Genuino UNO" 書込装置: "AVRISP mkII" と接続設定を行います。

f:id:kumak1:20161210174543p:plain

Arduino IDE には AVR ライターのサンプルプログラム(スケッチ)が収録されているので、これを選択、Arduino UNO へと書き込みを行います。

f:id:kumak1:20161210174935p:plain

f:id:kumak1:20161210175715p:plain

これで Arduino UNO の準備は完了です。

Pro Micro を Arduino Micro 化

早速 Arduino UNO を使って Pro Micro へ書き込みをできる様、以下の通りに接続します。

UNO Pro Micro
GND GND
10 RST
5V VCC
13 (SCLK) 15 (SCLK)
12 (MISO) 14 (MISO)
11 (MOSI) 16 (MOSI)

実際に接続した図です。

f:id:kumak1:20161210200322j:plain

接続できたら、ボード: "Arduino/Genuino Micro" シリアルポート: "Arduino/Genuino UNO" 書込装置: "Arduino as ISP" と設定し、ブートローダを書き込みます。

f:id:kumak1:20161210203106p:plain

ブートローダが書き込み終えたら、Arduino UNO はもう取り外してしまって構いません。

ハードウェアの実装

まずはアルミ板からですが、金属加工の道具を持っていないため、下の図面を Illustrator でおこして(CADとかよくわからない・・)東急ハンズのお兄さんに加工してもらいます。

f:id:kumak1:20161210214054p:plain

アルミ板の加工が終われば、スイッチの組み付けを行います。穴にピッタリはまる!とはならないため、厚手の両面テープをアルミとスイッチの間に貼り付けることで、隙間を埋め接着します。 (接着剤は取り外しできなくなるので避けた。グルーガンを持っていれば、それが最適解な気がする。)

f:id:kumak1:20161210200335j:plain

接着物はやはりピンセットで作業を行うと捗ります。

f:id:kumak1:20161210200352j:plain

接着し終えたら、 Pro Micro とクリップやジャンパピンでつなげて仮実装します。 Mac と Pro Micro も USB ケーブルで繋いでしまいましょう。

f:id:kumak1:20161211122049j:plain

ソフトウェアの実装

短押し長押し で挙動が変わるキーを実装したいなと思いました。(具体的には Karabiner で設定する様な、短押しで かな/カナ 変更、長押しで となるキー操作ができるようにしたい) サンプルプログラムは以下の通り。

#include <Keyboard.h>

const uint8_t PIN_MAX   = 21;     // Pro Micro のPIN数
const uint8_t PIN_R_B_0 = 9;      // 仮実装で使う Pro Micro のPIN番号

uint8_t keyPressedTimes[PIN_MAX]; // キーボードが押下されている時間を記録する

void setup() {
  // キーボートとして認識させるPINの初期化
  for(uint8_t i = 0; i <= PIN_MAX; i++) {
    switch (i) {
        case PIN_R_B_0:
            pinMode(i, INPUT_PULLUP);
            keyRelease(i);
            break;
    }
  }

  Keyboard.begin();
}

void loop() {
  keyRead(PIN_R_B_0, 'a', 'b');

  delay(10);
}

/**
 * PIN の状態から、キーボードを動作させる
 *
 * @param uint8_t pinNumber   キーボートとして認識するPINの番号
 * @param char onClickKeyCode 短押し時のキーの振る舞い
 * @param char onPressKeyCode 長押し時のキーの振る舞い
 */
void keyRead(uint8_t pinNumber, char onClickKeyCode, char onPressKeyCode) {
  if (digitalRead(pinNumber) == LOW) {
    if (isKeyLongPress(pinNumber)) {
      Keyboard.press(onPressKeyCode);
    } else {
      keyPress(pinNumber);
    }
  } else if (isKeyPress(pinNumber)) {
    if(isKeyLongPress(pinNumber)) {
      Keyboard.release(onPressKeyCode);
    } else {
      Keyboard.write(onClickKeyCode);
    }
    keyRelease(pinNumber);
  }
}

/**
 * キーが押されたことを記録する
 * 
 * @param uint8_t pinNumber キーボートとして認識するPINの番号
 */
void keyPress(uint8_t pinNumber) {
  if (!isKeyLongPress(pinNumber)) {
    keyPressedTimes[pinNumber]++;
  }
}

/**
 * キーが離れたことを記録する
 * 
 * @param uint8_t pinNumber キーボートとして認識するPINの番号
 */
void keyRelease(uint8_t pinNumber) {
  keyPressedTimes[pinNumber] = 0;
}

/**
 * キーが押されているか確認する
 * 
 * @param uint8_t pinNumber キーボートとして認識するPINの番号
 */
bool isKeyPress(uint8_t pinNumber) {
  return keyPressedTimes[pinNumber] > 0;
}

/**
 * キーが長押しされているか確認する
 * 
 * @param uint8_t pinNumber キーボートとして認識するPINの番号
 */
bool isKeyLongPress(uint8_t pinNumber) {
  return keyPressedTimes[pinNumber] > 20;
}

プログラムの書き込み

Mac と Pro Micro をUSBケーブルで接続し、ボード: "Arduino/Genuino Micro" シリアルポート: "Arduino/Genuino Micro" 書込装置: "AVRISP mkII" と設定し、プログラムを書き込みます。

f:id:kumak1:20161211015731p:plain

書き込み後にキーボードを押してみると、短押し時には a 、長押し時には b が入力されるようになりました!

おわりに

自作キーボードの良さは拡張性の高さにあります。 自分で好き勝手にできるので、自分の動作環境に依存するものを容赦なく作れるのが魅力でもあります。

  • ESC キーなどの単一機能を実装
  • 短押し長押し で挙動が変わるキーを実装して Karabiner への依存を減らす
  • SHIFT のトグルボタン(iOSのshift 2回押しみたいな挙動)の実装
  • API連携による、定型文tweet、プロダクトのデプロイ
  • コンソール連携による、Git pull、タスクランナーの動作

などなど、作りたい・作れるものを挙げればキリがありません。 時間とスキルの関係上、「完璧に作り終えた!」という段階までできなかったのが悔やまれますが、あとは実際に使用してみながら調整して行こうと思います。

明日のアドベントカレンダーの執筆者は zipper さんです。めっちゃテッキーな話をしてくれそうだー。

参考記事

Unity の Cube を使う時、側面の天地が揃う UV 作った

Unity の Cube、便利ですね。 とりあえずイメージを掴むためのワイヤーフレームとして、ポンっと追加できるの最高です。

そのまま使う時の、そうじゃない感

ただ、ベタ塗りの色を置いておく場合は良いのですが、テクスチャ画像を貼り付けると、 「違う、そうじゃない」ということもありがちです。

例としては、壁を Cube で作ってテクスチャを当てた際、 側面の上下が反転してしまうのでそのままだとチグハグになりがちです。

f:id:kumak1:20161009173713p:plain こんな感じ。矢印は全て上を向いてもらいたい。

そこで、パパっと UV を書きました。

UV について

UVの概念についてはこちらがわかりやすいかな answers.unity3d.com

要は、ポリゴンの頂点が、テクスチャのどの座標と対応するか、の対応表です。

作成した UV

こんな感じ。全部 Start に書かず、 Awake に書くことで描画遅延をなく・・せてるはず。

using UnityEngine;
using System.Collections;

public class WallUv : MonoBehaviour {
    Vector2[] uv = new Vector2[24];

    void Awake()
    {
        // 左 : -x
        uv[2].x = 1.0f; uv[2].y = 1.0f;
        uv[3].x = 0.0f; uv[3].y = 1.0f;
        uv[0].x = 1.0f; uv[0].y = 0.0f;
        uv[1].x = 0.0f; uv[1].y = 0.0f;

        // 上 : +y
        uv[4].x = 0.0f; uv[4].y = 0.0f;
        uv[5].x = 1.0f; uv[5].y = 0.0f;
        uv[8].x = 0.0f; uv[8].y = 1.0f;
        uv[9].x = 1.0f; uv[9].y = 1.0f;

        // 後 : -z
        uv[23].x = 1.0f; uv[23].y = 0.0f;
        uv[21].x = 0.0f; uv[21].y = 1.0f;
        uv[20].x = 0.0f; uv[20].y = 0.0f;
        uv[22].x = 1.0f; uv[22].y = 1.0f;

        // 前 : +z
        uv[19].x = 1.0f; uv[19].y = 0.0f;
        uv[17].x = 0.0f; uv[17].y = 1.0f;
        uv[16].x = 0.0f; uv[16].y = 0.0f;
        uv[18].x = 1.0f; uv[18].y = 1.0f;

        // 下 : -y
        uv[15].x = 1.0f; uv[15].y = 0.0f;
        uv[13].x = 0.0f; uv[13].y = 1.0f;
        uv[12].x = 0.0f; uv[12].y = 0.0f;
        uv[14].x = 1.0f; uv[14].y = 1.0f;

        // 右 : +x
        uv[6].x  = 0.0f; uv[6].y  = 0.0f;
        uv[7].x  = 1.0f; uv[7].y  = 0.0f;
        uv[10].x = 0.0f; uv[10].y = 1.0f;
        uv[11].x = 1.0f; uv[11].y = 1.0f;
    }
        
    void Start () {
        MeshFilter mf = gameObject.GetComponent<MeshFilter>();
        mf.mesh.uv = uv;
    }
}

実行結果

スクリプトを cube に Add Component して実行します。と、狙ったとおり側面は全てY軸の方向を天としました。 バッチリですね。 f:id:kumak1:20161009175022p:plain

雑記

でもま、ゲームで本気のモデルを作るときは、Cube ではなく、専用モデルとUV Blender 等々で生成、専用テクスチャをゴニョゴニョ・・なので、実用性は謎です。