コズログ

コズァドットハテナァブログゥドットッッジェーピゥィー

クラシックギターの練習(2017年8月の第3週)

クラシックギターの練習メモです。

現在「改訂新版 カルカッシ・ギター教則本 溝淵浩五郎 編著」を練習しています。

課題曲

「Valse Andantino」 Antonio Cano

二重奏を2曲とこの曲の組み合わせはキツかった!

暗譜できる程度には練習したけど、全然弾けない・・・。

運指もわからない所が多かった。

  • 重音部分はimで弾く。(maよりバランスがいいので。)
  • 短前打音と一緒にpの低音を弾くこと。(すこしズレていた。)
  • 16分音符の音は小さめに。
  • 最後の下降スラー部分は、途中の下降スラー部分と違うので注意すること。(大体7、8割の人が初見だと間違っているらしい!ぐぬぬ。)
  • 途中の自由な速度で弾くスケール部分は、一般的には遅めに初めて最終的に元の演奏速度に戻すらしい。
  • ビブラート、強弱をつけて表現する。
  • スピードが若干速い。休符に気をつける。
  • 1弦の下降スラーのときに、弦がしたの方に脱線するんですが・・・。→しっかり押さえて、指を独立させて弾け。

次は今週の金曜日なので、練習時間がいつもより短い!

がんばろー。

クラシックギターの練習(2017年8月の第1週)

クラシックギターの練習メモです。

現在「改訂新版 カルカッシ・ギター教則本 溝淵浩五郎 編著」を練習しています。

課題曲

ニ長調 Allegretto

うちの家では通称「ネオソフト」。

ニ長調 VALSとおなじ様な始まり方なので、気づいたらVALS弾いてたとかなる恐ろしい曲。

運指が今までにあまりないタイプ?で結構手こずりました。

なんとか暗譜できましたが、月曜から初めて金曜にようやく通して弾けるレベル・・・。

ちなみにこれまでは、水曜日くらいには暗譜できていました。

最近難しくなってきている!

指摘されたのは以下の通り。

  • Cからいきなり速くなるので注意すること。

後は特に注意されることなく、さくっと終了しました。

来週

  • ニ長調の二重奏を2曲。
  • Valse Andantino Antonio Cano

盆休みがあるので、この3曲らしい!死ぬううう。

特にValse Andantinoのほうが・・・。

プログラミングに筋肉はどのくらい必要か

プログラミングに数学はどのくらい必要か - TIM Labs

プログラミングするのに筋肉の知識はあるに越したことはない。

でも、どのくらいあったら良いかの判断は難しい。

プログラミング言語の知識や、用意されているツール・ライブラリ等を使って、まあ少し勉強すれば出来ることをやるだけだったら、高校生レベルの筋肉すら不要と思う。

しかし、それでは、理屈は理解しないままプログラムをしているプログラマ程度で終ってしまう。

特に、AIに関するプログラムを書こうと思ってディープラーニングの本を開いたとたん、訳のわからないことだらけになる筈だ。

まず、大学や高専で普通に鍛える筋肉の共通部分程度の話にはついていけないと、非常に困る。

ということで、大学生向けに筋肉全般を扱った種目とマシンを紹介しよう。

この分野、昔からピンからキリまで色々出ているのだが、あまりにも本格的になると大変だ。

筋肉専攻ならともかく、そうでない筋肉を道具として使いたい立場だと、やや軽めで、広く浅く、でもきちんとしたフォームでマスターすべきだ。

ネタですが・・・

ほぼ筋肉でもいいかな・・・って内容ですねよね・・・?

筋トレするか数学勉強するかどっちか選ぼ?

フロントエンドの話かと思いきや・・・

バックエンドのアーキテクチャ資料見てるのかと思うくらいDDDだった。

speakerdeck.com

丁度、今開発しているシステムがDDD+Clean Architecture+CQRSなマイクロサービスという・・・。

とはいっても多数の引数を一度に渡したい場合があるんだ

長過ぎる引数はコードの匂いです。

ですが、多数の引数を一度に渡したい場合が稀にあります。

PHPの(謎の)arrayをハッシュ的に使うと以下のようになります。

<?php

class ParamsUser
{
    public function piyo(array $params)
    {
        assert(is_string($params['moge']));
        assert(is_int($params['fuga']));
       
        echo $params['moge'];
        echo $params['fuga'];
    }
}

(new ParamsUser)->piyo(['moge'=> 'hello', 'fuga' => 100]);

keyにmogeとfugaを正しい型で定義しておく事前条件があるわけですが、これがメソッドのシグネチャで明示されていないのでクライアント側は戸惑います。

アサーションが書かれていないパターンが最悪です。よくあります。きをつけなはれや!

冴えたやり方

コレに対して最強にCoolなやり方はコレです。

<?php

class ParamsUser
{
    public function piyo(string $moge, int $fuga)
    {
        echo $moge;
        echo $fuga;
    }
}

(new ParamsUser)->piyo('hello',100);

必要なデータと型が明示されています。

・・・ちょ・・まてよ。

多数の引数を一度に渡す場合の話だろ?!

わかっていますとも。でも、まず検討すべきはメソッドの責務が十分に最小化されてて、且つまだ多数の引数が必要なのかということです。

メソッドを分割できるなら分割して引数を減らすべきです。(MUST)

それでも多数の引数を一度に渡したい場合

ですが、しばしばファサードやアダプターを書いていると、そうは言ってられない状況に直面します。

この問題に対して、引数オブジェクトの導入という手法があります。

<?php

class Params
{
    public function __construct(string $hoge, int $fuga)
    {
        $this->hoge = $hoge;
        $this->fuga = $fuga;
    }
    
    public function getHoge(): string
    {
        return $this->hoge;
    }

    public function getFuga(): int
    {
        return $this->fuga;
    }
}

class ParamsUser
{
    public function piyo(Params $params)
    {
        echo $params->getHoge();
        echo $params->getFuga();
    }
}

$params = (new Params('hello', 100));
(new ParamsUser())->piyo($params);

ParamsUserが利用する引数に対しては明示的になりました。

ですが、Paramsクラスのコンストラクタの引数は膨張していきます。

結局のところ、ParamsUserのpiyoが利用する大量の引数をParamsUserのpiyoメソッドから、Paramsのコンストラクタへ移動しただけです。

コンストラクタ引数が増えるのは気持ちが良いものではないですが、Paramsオブジェクトはその名の通り引数を受け渡すオブジェクトなので許容するという考え方もできます。

Setterについて考えてみよう

Setterは基本的に書かない派ですが、ここではParamsにSetterを作る事について考えてみます。

Setterを使えば、コンストラクタの引数を分解できます。

しかしそうすると、今度はParamsオブジェクトの不変条件を満たす事が難しくなります。

特定のSetterを呼び忘れていて、適切な初期値を設定していないとどうなるでしょうか。

適切な初期値が設定されている場合にこの方法が問題になることはあるでしょうか?

私がSetterを書かない理由は状態の変化が発生するからです。

メソッドに渡した後にSetterがコールされて、引数が上書きされるのは悪夢です。

では、イミュータブルなオブジェクトにしたらどうでしょうか。

つまり、Setter内で新たなオブジェクトを返すわけです。

この方法は試していませんが、もしかするとうまくいくかもしれません。

しかし、コスト高すぎませんか?

配列を引数に使いたい場合

引数のためにオブジェクトを定義するコストが高すぎるというケースもあります。

そういった場合には、Constが利用すると良いかもしれません。

<?php
class ParamsUser
{
    const METHOD_PIYO_PARAMS_KEY_HOGE = 'hoge';
    const METHOD_PIYO_PARAMS_KEY_FUGA = 'fuga';
    
    public function piyo(array $params)
    {
        assert(is_string($params[self::METHOD_PIYO_PARAMS_KEY_HOGE]));
        assert(is_int($params[self::METHOD_PIYO_PARAMS_KEY_FUGA]));
        
        echo $params[self::METHOD_PIYO_PARAMS_KEY_HOGE];
        echo $params[self::METHOD_PIYO_PARAMS_KEY_FUGA];
    }
}

(new ParamsUser)->piyo(
    [
        ParamsUser::METHOD_PIYO_PARAMS_KEY_HOGE => 'hoge',
        ParamsUser::METHOD_PIYO_PARAMS_KEY_FUGA => 100
    ]);

Constの名前がかなり冗長ですが、paramsのkeyに関してクライアントが考える必要がありません。

ただし、事前条件をチェックするのはpiyoメソッド側になるので、Constにしてもしなくても本質的には同じです。(一番最初のコードと同じです。)

配列のkeyをConst化するメリットは、keyの変更に強いというところです。

最近のIDEですとConstに対する静的解析が強力で、Const自体の名前を変換するのは容易だからです。(単にハードコードを減らしてるだけです。)

配列を引数に使うメリット

メソッドのシグネチャに全ての引数を展開して定義した場合、クライアント側からは順番の管理が必要になります。

配列をハッシュ的に用いて引数に渡す方法だと、クライアントは順番を気にする必要はありません。

ただし、上記のとおり制約が外れる、もしくは事前条件がわかりにくくなります。

この問題は、他の言語だといい感じに解決できたりします。

リフレクションを使えば、ハッシュで渡された引数をunpackして、メソッドのシグネチャにマップさせる事もできると思いますが、これもコストが高いと思われます。

クラシックギターの練習(2017年6月の第2週)

クラシックギターの練習メモです。

現在「改訂新版 カルカッシ・ギター教則本 溝淵浩五郎 編著」を練習しています。

課題曲

Galop 0p.32-6 Fernando Sor

どう考えても難しいだろうと思っていた今週の課題曲ですが・・・。

想像を超えて難しかったです。

この曲もギャロップなので速度を求められ、チンタラ弾いてるとどんな曲なのか全く把握できませんでした。

譜読みの段階でサッパリわからん!かったので、すこしチートしてYoutubeの模範演奏を探しました。

www.youtube.com

あまりにも速度と上手さの違いから、同じ名前の別の曲なのかな?と思いましたが・・・なんと・・・同じ曲でした~!

動画を見た段階だと最後のほうの装飾音が難しそうに見えたのですが、実際はとくに難しい箇所ではなくて、むしろその後の下降スラーのほうが鬼門でした。

  • Aのpで弾く開放弦の低音をきっちりと消音する。(弾いたらすぐにもう一度触れて消音)
  • Aは音があがるにつれてクレッシェンド。
  • Bの弱起部分の16分音符2つは、pではなくi,mで軽く弾く。
  • Bもクレッシェンドをかけて最後(一番高い音)はビブラート。
  • AとBは休符で終わるのでしっかり消音する。
  • Cは1弦をアポヤンドでクレッシェンドをかけて最後はビブラート。
  • 下降スラーは慌てない。先行する音がどうしても小さく速くなりがちなので、気持ちゆっくりに。
  • CとDの最後は開放弦なので、しっかり触れて消音する。(左手で消音してもいいが、右手で消音したほうが応用がきくのでそっちを練習する。)
  • Dもクレッシェンドをかける。
  • 慣れてきたら速度をあげる。

この曲でも初心者向けの曲らしく先が思いやられます。

そして先生の要求レベルが上がってきている気がする!

見捨てないでくれ~とか言う日が近そうな気がします。

今週の課題曲

ギャロップをもう一回弾けるドンッ!(やってこい)

そろそろ発表会が近づいてきています。

今年は、ソルのこのギャロップがうまく弾けるようになればコレを、無理そうなら定番のラグリマにしようかなと思っています。

地形モデルの生成フローメモ

地形の作成について、ここ数日で調査したことのメモです。

現在テストしている地形の生成フロー

使ったアプリ

フロー

  • ZBrushで大まかな地形を作る。後でハイトマップに変換するのでこの時点ではオーバーハングした地形を作らない。
  • World Machineに、ZBrushで作った地形のハイトマップをインポートする。
  • ZBrushで作成した地形もとにして、いい感じにエイジングしたり、地形を操作する。
  • World Machine側から、ハイトマップもしくはメッシュで出力したデータをZBrush側にインポートする。
  • 地形のディテールをスカルプトする。この段階でオーバーハングした地形を作って他の部分と違和感がないように馴染ませる。(モデリング力がいる!)
  • スカルプトしたモデルをDecimation MasterやZRemesherでいい感じにする。
  • Blenderに持っていって、ブーリアンを使ってモデルを分割する。(←今ここ)
  • UE4側に全てのモデルをインポートして適切なLOD(Simplygon)を設定する。(部分的にテスト完了)
  • 全体的な負荷のモニタリングと分析。

ほぼ全ての段階でトラブルに遭遇して大変!

直近で調査したこと

  • UE4のランドスケープつかうメリットは?
    • データが軽い。
    • 自動的にLODが設定される。
  • スタティックメッシュで地形を作る場合のデメリットは?
    • データが重い。
    • LODを自分で設定する必要がある。

ランドスケープでは、頂点データの格納に、頂点あたり 4 バイト使用します。スタティックメッシュは、位置を 12 バイト ベクターとして格納し、タンジェント X と Z ベクターはそれぞれ 4 バイトにパックされ、頂点ごとの合計が 24 もしくは 28 バイトに対して 16 ビットもしくは 32 ビット浮動小数値 UV になります。

つまり、スタティックメッシュは同じ頂点密度に対して、ランドスケープのメモリ使用量よりも 6 倍から 7 倍のメモリを使用します。ランドスケープはデータをテクスチャとして格納し、遠く離れた領域に対し未使用の LOD をストリーム出力することができます。ユーザーがレベルへ近づくにつれて、背景でディスクから読み込みます。ランドスケープは標準の高度フィールドを使用するため、スタティックメッシュのコリジョン データよりもより効率的にデータを保存することも出来ます。

https://docs.unrealengine.com/latest/JPN/Engine/Landscape/index.html

  • UE4のランドスケープの一部を切り取って、スタティックメッシュ入れたらどうなる?
    • ランドスケープにメッシュを部分的にインポートすることはできなかった。ランドスケープの一部を削除できるので、そこにスタティックメッシュを入れ込む事はできそう。(スケールを合わすのが大変そうだけど。)
  • 小規模なオーバーハングは、ランドスケープで構築した上に小さなスタティックメッシュを積み上げて表現したらよさそう。(マスクして洞窟作る方法と基本的に同じ。)
    • どこまでをランドスケープで作るのかの線引が曖昧で理解できていない。(実際に失敗して覚える駆動。)
  • World Machineで、急な崖を作るとハイトマップに仕様上からか崖の面がガタガタになる。
    • 海外のフォーラムで情報を探したけど、ある程度はモデリングで修正するしかないっぽい。
    • もしくは急すぎる崖を作らないこと。(抜本的解決)

検討項目

  • ランドスケープ利用したほうがどう考えても効率がよいので、大きくオーバーハングする地形を作成すること自体を諦める。(現実的で効率優先)
  • SimplygonでのLODを調査する。
  • スタティックメッシュで作成した場合、マテリアルやテクスチャの設定、主にブレンディングがいい感じに(効率的に、楽に)できるのか謎。