キノコの自省録

日々適当クリエイト

熱源に向かって自走するシアーハートアタックを作った

ジョジョの奇妙な冒険第4部に登場する、遠隔操作型のスタンド「シアーハートアタック」を自作しました。

シアーハートアタックとは

  • 吉良吉影のスタンド「キラークイーン」の左手から発射される爆弾戦車
  • 脚はキャタピラ
  • 熱源に向かって自動追尾する
  • 丸っこい爆弾型ボディーの前面に猫型の頭蓋骨が配置されている
  • 「コッチヲ見ロッ」と喋る

というシロモノです。

爆発は無理ですが、

  • 熱源に向かって自走する
  • キャタピラで駆動
  • 「コッチヲ見ロッ」と喋る

この辺の設定を守って製作してみました。

youtu.be

造形は初めてなので、かなりボッコボコです。 これでもやっているうちに作り方を覚えて、大分マシになりました。

ユーザーストーリーマッピング - Jeff Patton

今年読んだ本の紹介その2。
ユーザーストーリーマッピング - Jeff Patton
https://www.amazon.co.jp/dp/4873117321
素晴らしい本です。超おすすめしておきます。


これは、アジャイル開発手法である、”スクラム”の最初に行う「ユーザストーリー(マッピング)」の解説です。
スクラムのわずか1プロセスについて、なんと1冊の本にしたということです。


基本哲学 - 完璧なドキュメント(要件定義など)は存在しない

0章ではっきり書いています。かなり痛快に。
ソフトウェア開発に携わったことがある人なら、要求とか要件とかという名の妖怪について、みんな一言あるでしょう。
要件定義書というのは、作るべきものが書いてあるものの、本当に作るべきものが十分書かれてはいません。
しかし、間違えたものを作ったら、誰かのせいになります。
それは仕様屋さんだったり、今までの慣習を知らないプログラマーだったり。


語りえぬものについては、沈黙しなければならない

そもそも論として、必要なもの全てが言語化できるわけではありません。
「可愛いキャラクター」がなぜ可愛いか、を言葉で説明できないように、言語化には限界があります
言外の意味に重要なファクターが多分に含まれることは、なんとなくイメージつくと思います。
しかし、言語化したときに、ごっそり抜け落ちます。
論理の外にあるものは、言語化できません。

※この辺りはamazon:リファクタリング ウェットウェアを読むと良いでしょう。


非言語要素をドキュメントで書き表せないのであれば、別の方法を取る必要があります。
それは、「共通理解を作る」ことです。
共通理解=共有ドキュメントではありません。
共通理解とは、関係者みんなが頭の中に思い描く完成図です。


では、共通理解とは、どのように構築すればよいのでしょうか?
その手法の一つが、本書のタイトルである「ユーザーストーリーマッピング」です。


本書のカバー範囲

ユーザーストーリーとは、簡単に言うと、
「プロダクトが描き出すストーリーを語ること」です。
ユーザーストーリーマッピングとは、
「ユーザーストーリーをポストイットでマップ化すること」です。
どんどん会話して、一緒にストーリーマップを作りましょう、というのがコンセプトです。
あくまでも主役はストーリーです。ポストイットマッピングのための補助ツールです。
ポストイットは言語化されたものなので、その段階で情報が落ちます。)
作られたマップは、プロダクトのバックログとして活用されます。


トーリーを語れといっても、様々な切り口があったり、その成果物の使い方があったりします。
また、良いストーリーとは、という側面でも考えるべきところがあります。
このようなストーリーにかかわる諸々が、300ページの本の中身となっています。
僅かアジャイル開発の前段階の1プロセスで300ページです。
ちなみに、「スクラム実践入門」という本では、
関連しそうなページを足しても、ユーザーストーリーについての説明は5ページくらいです。


逆に、ユーザーストーリーマッピングにはポストイットを使用しますが、
それ以外の点については、betterは説明していますが、mustにはしていないような印象を受けます。
(極端な悪手にはNoを出していますが)
メソッドにとらわれるより、ストーリーを語りましょう。


最後に

感銘を受けた言葉を。

私はスコープ(仕事の範囲)がクリープ(知らない間にふくらむ)することはないと思っている。単に理解が進んだだけだ。

その通りだと思います。

フーリエ変換のナイキスト周波数についてもう少し

音(声)の高低を検出する方法を真面目に書く
http://d.hatena.ne.jp/kinokorori/20130328/1364469421

この記事に最近ナイキスト周波数について記述を追加しました。
……追加しましたが、ちょっとだけのつもりが長くなった割に説明不足で、
なんだかよくわからなくなりました。なので、再度書き直しします。


ナイキスト周波数

ナイキスト周波数とは、サンプリング周波数の半分の周波数のことです。
一般的なwav形式のサンプリング周波数44100Hzならば、22050Hzということです。
これが、FFTで正しく検出できる、最大の周波数となります。


つまり、検出したい周波数があるならば、その倍のサンプリング間隔が必要ということです。
これを標本化定理と言います。
標本化とはサンプリングのことですので、サンプリング定理とも言います。


折り返し雑音

44100Hzでは話がしづらいので、もう少し周波数を下げてお話しします。
20Hzのサンプリング間隔ですと、ナイキスト周波数は10Hzになります。
では、ここに15Hzの周波数成分を含む信号が入ったときはどうなるでしょうか?

標本化定理により、15Hzは正しく検出できない、というのは上述の通りです。
15 - 10 = 5Hz分、折り返して跳ね返ってきます。
つまり、10 - 5 = 5Hzの信号に重畳されてしまいます。
本当は5Hzじゃないのに、5Hzの信号として扱われるので、ノイズとして顕在化します。
これを折り返し雑音(エイリアシング)と言います。


折り返し雑音を避けるため、高周波成分は、
サンプリング前にローパスフィルタでカットするということが良く行われるようです。


図解

「15Hzが5Hz?意味わからん。三角関数だし円運動だから折り返してきそうなのはなんとなくわかるが。」
みたいな感想を抱くことでしょう。
このナイキスト周波数は”標本化”定理、つまり連続信号を離散信号に落とした時に発生します。
アナログ世界ではなく、デジタルです。インテグラルではなくシグマです。

図を見ると一発でわかります。
下の図は、1秒間に100個のサンプリングを行った場合(つまりサンプリング周波数100Hz)に、
5Hzと15Hzのサイン波を図示したものです。


点をつないで連続波形にしているので、100Hzということがわかりにくいですが、
離散表現にすると、下の図のようになります。

この棒が立っているところだけが、実際に観測された(デジタル化された)値です。
見た通り、5Hzと15Hzは、明らかに別物だということがわかります。
当たり前だろ何言ってんだこいつレベルです。


さて、サンプリング間隔を1秒間に100個から、1秒間に20個に落としてみましょう。
すなわち、サンプリング周波数20Hzです。
ナイキスト周波数10Hzなので、15Hzは正しく検出できないはずです。
では、まずは5Hzのサイン波から。

次は15Hzのサイン波です。

なんと、15Hzに見えません。5HzをX軸で反転させたように見えます。
これを線で滑らかに補間して図示すると、こんな感じになります。

原信号は15Hzにも関わらず、完全に5Hzの信号に見えます。位相が反転しているだけです。


同じように、12Hzでも考えてみましょう。
ナイキスト周波数10Hzなので、2Hz折り返してきます。
つまり8Hzと12Hzが同じに見えるはずです。
まずは8Hzです。


次に12Hz。


やはりX軸で反転したグラフになります。


これらの図の通り、ナイキスト周波数を上回る周波数の信号は、正確に復元できないことがわかります。
口で説明しても、なんだかわかったようなわからないような感じがしますが、
実際に図示すると割とイメージが掴みやすい現象だと思います。
数学的に、数式からも証明できます(私ができるとは言ってない)。

今年読んだ本 - Effective Modern C++

ブログの更新をサボり過ぎということで、リハビリついでに2016年に読んだ本を適当に紹介。

今回はEffective Modern C++

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

評価の通り、良い本でした。

内容紹介

C++プログラマから絶大な支持を集めるC++界のカリスマ、スコット・メイヤーズが、優れたC++プログラムはどのように書けばよいのかを指南。
C++をすみずみまで知り尽くした著者が、効果的かつ堅牢、移植性の高い優れたC++プログラムを書くノウハウを42項目にまとめています。
さらに上を目指したい中上級者必携の一冊です。C++11/C++14対応。

この内容紹介では少々わかりづらいですが、C++11/C++14で追加された新機能について、使用上のポイントを重点に42項目を記載した本です。

対象は内容紹介の通り、完全に中上級者向け。特にフレームワーク設計などの、C++ソフトウェアアーキテクト向けです。なぜなら、C++11で追加された内容は、overrideやラムダなどの便利機能はありますが、型推論や右辺値参照やユニバーサル参照(ムーブ)、constexpr、3種類のスマートポインタなど、フレームワークの柔軟性やパフォーマンスに特化したものが多いためです。
そして、この辺りの新機能は、よくわからないまま設計に使用してしまうと、わかりづらく、影響範囲の大きいバグを生み出してしまいます。
この本では、その辺りを、様々な使用シーンを想定して記載しています。


しかし、(C++98までの)C++が抱える課題を多少なりとも理解していないと、まったく何を書いているのかわからないと思います。
具体的には、コンストラクタ/デストラクタの仕組み、メモリコピーがいつ発生するか、例外規定、templateの型推論や従属型、といったあたりの知識がある程度要ります。
なお、この点については、Effective C++, Exceptional C++, Modern C++ Designなどに散発的に書かれています。Exceptional C++と、Modern C++ Designは日本ではピアソンとの契約の関係で絶版になっていますが、古本市場ではそれなりに出回っています。


ある程度C++がわかる人は、逆に読んでおいた方が良いと思います。特に、C++11/14は聞いたことがあるけど、中身はよく知らないという方は是非。C++11/14といった変態言語に興味を示す人ならば、おそらくアーキテクトとして将来を嘱望されている可能性が高いでしょうから、絶対に損はないと言えます。それに、C++11/14について書かれた日本語で読める本は、これと江添さんの本しか今現在ありません。


ちなみに、C++は闇の言語か否かみたいな小噺が書いてありますが、私からはなんとも言えません。
右辺値参照について説明しても、みんな怪訝そうな顔を向けるだけでした。。。

デッサン用ミラーカメラ ver1.3.0をリリースしました

デッサン用ミラーカメラver1.3.0をリリースしました。
2回画面をタップすると、一時停止するようになりました。
あと、デザインをアイコン含めて見直しました。
UIはほとんど弄っていません。

https://itunes.apple.com/jp/app/id637583972?mt=8


今回の一時停止機能は、レビューを見て、
「あ、確かにあると便利かも」と思い、採用させていただきました。
確かに、止められた方が確認しやすいです。
止めたままでも反転と解除、グリッド表示切替が可能です。


あと、レビューでよく見かけるのは撮影機能ですかね。
リアルタイム性重視なので、一時停止があれば撮影機能はとりあえずいいかなあと思っています。
スクショがありますし。
本体機能の邪魔にならずに実装できれば、というところですかね。


他に見かける要望は、保存した画像の反転あたり。
これはUIがざくっと分断されてしまうこと、そういうアプリがたぶんあることから、
実装は消極的です。


このアプリは、「小さいことは良いことだ」をコンセプト的に作ってるので、
ボタン1つ置くのも、結構躊躇います。
設定やバージョン情報すらないですからね。なにしろ。


なお、サイズが5Mを超えてしまいましたが、
大体がアイコンとスプラッシュ(起動画面)のバリエーションが増えてしまったせいです。

Witch Cried反省会

Appliv様にWitch Criedを紹介していただきました。
http://app-liv.jp/1104623991/


それにしても、使用環境も利用者も限られる、
ニッチ中のニッチアプリなので、DL数は相当厳しいものになるだろうと予想はしていましたが、予想以上でした。
大苦戦。
1日で作ったアプリでも追い抜けるほどです。

Witch Criedについて 音声認識編

プレイ環境が超限られるゲーム「Witch Cried」の音声認識についてのお話し。


最近では、Google音声認識やSiriを始め、音声認識エンジンの競争が活発化しています。
このような既存の素晴らしい音声認識エンジンがあるので、こういうゲームを作る場合、当然それをありがたく使わせていただいて作ろうと考えると思います。
自分もそうでした。
しかし、魔法詠唱という用途には微塵も役に立たないことに、5分とかからず気づきました。
理由は以下の通り。

  1. 自然な言語しか入らない
  2. ネットワークが必要で、レスポンスも遅くなる
  3. 勝手に打ち切られる
  4. iOSだとGoogle音声認識が使えず、SiriもAPI公開していない

自然な言語しか入らない

音声認識の主目的は検索なので当然といえば当然。
ファイアのような普通の単語なら当然入りますが、よくわからない言語や、言い回しが特殊なものは、まともに認識されません。
ずっと同じ認識結果なら、百歩譲って使えるかもしれませんが、1文字違うだけで、その魔法を発動すべきか否かの判断が難しくなります。日本語なら漢字がある分尚更大変です。
この1つ目の問題の時点で、もう既存の音声認識エンジンを使用するのは無理です。

ネットワークとレスポンス

最近のスマホでは、ローカル音声認識が入っていたような覚えもありますが、ネットワーク環境じゃないと基本使えなかった気がします。逆にネットワーク介してしまうと、間違いなくレスポンスが悪くなります。ゲームとしてはかなり致命です。やっててイライラするでしょう。

勝手に打ち切られる

間が空くと、勝手に終話と判断されてしまいます。この欠点に目をつぶったとしても、今度は秒数制限に引っかかります。つまり長い詠唱も打ち切られてしまいます。このゲームでは、これは結構致命的です。

iOS問題

Androidアプリという策もありますが、Androidはハードウェア使うアプリは鬼門なので、
あまりやりたくないというのが本音。
iOSと一緒ならともかく、単独リリースは避けたい。

ということで

既存の音声認識エンジンは、目的に合わないため、仕方なく自作。
といっても、そんな大層なことはやっていません。
DTW(Dynamic Time Warping, 動的時間伸縮法)を使って振幅スペクトルを比較することをベースにした、
音声認識の古典的手法を取っています。
現代の音声認識は、特徴抽出+言語辞書を利用するのが一般的だと思いますが、
言語辞書を噛ませた時点で、目的と合わなくなります。
そのため、音響特徴抽出を、ダイレクトに類似計算しているのが、今回の音声認識エンジンです。


あ、ちなみにこの魔法回路を魔道エンジンと呼んでいます。
どうでもいいですね。

課題

未公開アプリなので、話者協力を集うことができず、ほとんど自分の声のみでテストしています。
正直不安です。特に女性の声。
シャウトアラームがめざましテレビで紹介された時、
筧さんの声があまり認識されていなかったのをみて、周波数帯域を絞り込み過ぎたことに気が付きました。
実家に帰ったときに姉の協力を得て若干調整しましたが、調整しきれたかどうか、というところ。


アルゴリズム自体の改良や、ノイズリダクションなど、他にもやりたいことはあるのですが、
一人じゃ手が回りません。