cmake で github のレポジトリを登録したがコンパイルできない
経緯
Windows で CLion 使った開発を趣味でしているが表題の件でハマった。どういう状況でハマったかを書く。
- コンパイラは MinGW を使用している
- Git は Windows でも Linux コマンドが使えるようなパスを通している
- cmake を使って github 上のレポジトリを ExternalProject_Add した
上記の食合せだと動かなくなる。
どうなるのか
症例1
経緯の状態のまま cmake を実行して github のレポジトリを clone し、submodule update --init --recursive
的なことまでは進むが、 MinGW がコンパイルをボイコットする。
CMake Error at C:/path/to/CMake.cmake:20 (MESSAGE): sh.exe was found in your PATH, here: C:/path/to/sh.exe For MinGW make to work correctly sh.exe must NOT be in your path. Run cmake from a shell that does not have sh.exe in your PATH. If you want to use a UNIX shell, then use MSYS Makefiles. Call Stack (most recent call first): CMakeLists.txt:8 (project)
症例2
じゃあパスに入ってる sh.exe 消したら進むんじゃね?と浅はかに考えて sh.exe をリネームした。
fatal: 'submodule' appears to be a git command, but we were not able to execute it. Maybe git-submodule is broken?
(◞‸◟)
どうするの?
Git のインストール時に UNIX ツール群へのパスを通さないオプションがあるので Git 消して再インストールすれば良い。 これでぼくは二日間帰宅後の時間をだいぶ無駄にした。
作りたいもののポエム4
概要
4つ目、そろそろ実装に行きたい。
ところでこないだ真理を思い出したので設計が非常に単純になった。
唐突に真理を思い出したんだけど、音符一音一音に対するモーフィングとかいらないんだった。要件が一個落ちて簡単になるぞ。
— コーラデブ@shurabaP (@shurabaP) 2016, 2月 18
どういうことかというと、ある音符内でのモーフィングは実は不要で、 もし音に表情を付けたいのであれば音符ごとの強弱だけで十分まかなえるということ。 何か根拠があるわけではないけれどぼくは研究者ではないし、 気持ちとしては作曲者なので経験則に従いたい。
作りたいもの
- UTAU 音源より表現力の高い音源形式
- ↑のファイル読み書き部分
要件
- 既存リソースを活かすために UTAU 音源からインポートをできること
- 波形情報と演奏情報とキャラクタ情報は厳密に分けて設計すること
- 欲を言えば複数音源を自在に切り替え、あるいは混ぜられるようにすること(キャラクタの枠組みを越えるべき)
データ設計
segment (切りだされた波形)
segment は波形ファイルへの参照と波形の切り出し位置、伸長の位置を指定する。
{ "id": "segment0001" "path": "akasatana.wav", "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100 }
- id: segment ID
- begin: 開始位置
- length: 波形長
- temporal_position: ビートの位置(先行発音相当)
- front_fixed_range: 前半の固定長(固定長相当)
- rear_fixed_range: 後半の固定長
mapping(発音・音程・Velocityと、波形との対応)
ある発音がある音程である Velocity で指定された際にどの波形をどの程度利用するのかというマッピングを表す。
{ "pronounce" : { "before" : "a" "this" : "k a" "after" : "s a" }, "segments": [ { "segment_id": "segment0001", "range" : { "begin" : { "velocity": 0, "note": 0 }, "end" : { "velocity": 127, "note": 63 } } }, { "segment_id": "segment0002", "note": { "range" : { "begin" : { "velocity": 0, "note": 64 }, "end" : { "velocity": 127, "note": 127 } } } } ] }
- pronounce: 発音
- before: 先行音の発音(optional)
- this: 発音
- after: 後続音の発音(optional)
- segments: マッピングされるセグメント群
- segment_id: セグメントの識別子
- range: このセグメントが使用される範囲
- begin: 範囲の開始位置
- end: 範囲の終了位置
途中でのモーフィングが要らないためこれだけで表現が可能である。 基本的に既存のサンプラーと全く同じ仕組みだが、発音による検索が必要になるイメージ。
メタ情報(音源の名前とか)
{ "id": "澪音此羽", "version": "1.0.0", "author": "Hal@shurabaP", "web": "http://blog.hatena.ne.jp/shurabaP", "icon": "example.png", "path_type": "url", "url": "http://blog.hatena.ne.jp/shurabaP/reine_koreha", "mappings": "example.mappings", "segments": "example.segments", "description": "例ね、これは。" }
細かい形式
- pronounce
${consonant} ${vowel}
の形式で表す。子音が存在しない場合は前半を省略する。
- velocity, note
- 0-127 の 128 段階の整数
- begin, length など時間の位置
- ミリ秒で記す、どうせボコーダーがあじゃこじゃやるのに窓幅とかあるし適当でええやろ
- path
- path_type
- file か url の文字列をとること
悩みどころ
segments, mappings を JSON の配列にするべきかそれともファイルごとにするべきか。
たぶんだけど一個にまとめておいて遅ければ分割するのを考えるほうがいい気がする。
作りたいもののポエム3
概要
一昨日からの続きやるよ。
作りたいもの
- UTAU 音源より表現力の高い音源形式
- ↑のファイル読み書き部分
その他要件
- 既存リソースを活かすために UTAU 音源からインポートをできるようにする
- 波形情報と演奏情報とキャラクタ情報は厳密に分けて設計すること
- 欲を言えば複数音源を自在に切り替え、あるいは混ぜられるようにすること(キャラクタの枠組みを越えるべき)
データの設計
音楽的コンテキストは必要ないという結論に達した。本質的に波形接続型歌声合成器はサンプラーなのだからマッピングさえあれば全て型がつくのである(きっと
segment (切りだされた波形)
segment は波形ファイルへの参照と波形の切り出し位置、伸長の位置を指定する。
{ "id": "segment0001" "path": "akasatana.wav", "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100 }
- id: segment ID
- begin: 開始位置
- length: 波形長
- temporal_position: ビートの位置(先行発音相当)
- front_fixed_range: 前半の固定長(固定長相当)
- rear_fixed_range: 後半の固定長
mapping(発音・音程・Velocityと、波形との対応)
ある発音がある音程である Velocity で指定された際にどの波形をどの程度利用するのかというマッピングを表す。
{ "pronounce" : { "before" : "a" "this" : "k a" "after" : "s a" }, "segments": [ { "segment_id": "segment0001", "note": { "before": 60, "this": 60, "after": 60 }, "velocity": 64 }, { "segment_id": "segment0001", "note": { "before": 60, "this": 60, "after": 60 }, "velocity": 64 } ] }
- pronounce: 発音
- before: 先行音の発音
- this: 発音
- after: 後続音の発音
- segments: マッピングされるセグメント群
- segment_id: セグメントの識別子
- note: 音高
- before: 先行音の音高
- this: 音高
- after: 後続音の音高
- velocity: ベロシティ
根本的には note, velocity の二次元平面上のマッピングなのでもうちょっとマシな書き方がありそう。 結構空間が広いのでデータ量が爆発するのが難点。
pronounce
${consonant} ${vowel}
の形式で表す。子音が存在しない場合は前半を省略する。
作りたいもののポエム2
概要
昨日の続きやるよ。
作りたいもの
- UTAU 音源より表現力の高い音源形式
- ↑のファイル読み書き部分
とりあえず一旦ここまで書けたらいいこととする。(大きく作って死ぬことが多い気がする)
その他要件
- 既存リソースを活かすために UTAU 音源からインポートをできるようにする
- 波形情報と演奏情報とキャラクタ情報は厳密に分けて設計すること
- 欲を言えば複数音源を自在に切り替え、あるいは混ぜられるようにすること(キャラクタの枠組みを越えるべき)
ざっくりとした設計
segment (切りだされた波形)
segment は機械的な意味しか有しない。構成としては波形ファイルへの参照と波形の切り出し位置、伸長の位置を指定する以外の機能を持たない。
{ "segments": [ { "id": "segment0001" "path": "akasatana.wav", "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100 }, { "id": "segment0002" "path": "akasatana.wav", "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100 } ] }
- id: segment ID
- begin: 開始位置
- length: 波形長
- temporal_position: ビートの位置(先行発音相当)
- front_fixed_range: 前半の固定長(固定長相当)
- rear_fixed_range: 後半の固定長
切り出しと伸長はこれだけあればいい。これ以上の情報は別の情報に切り分けるべきだ。 UTAU の oto.ini は音楽的コンテキストを含まないのでこの設定は UTAU で言えば oto.ini に等しい。
切り出し部分についてはこれで良い。このレイヤーには発音や音程など発音のコンテキストを混ぜてはいけない。
phoneme (発音と音符の一断片)
phoneme は音楽的な一断片を表す。切りだされた波形とそれに対するメタ情報からなる。
{ "phonemes": [ { "id": "phoneme0001" "segment_id": "segment0001", "context" : { "pronounce": { "previous" : "-", "this" : "a", "next" : "k a" }, "note" : { "previous" : 60, "this" : 60, "next" : 60 }, "tempo" : 120, "strength" : 0 } } }, { "id": "phoneme0002" "segment_id": "segment0002", "context" : { "pronounce": { "previous" : "a", "this" : "k a", "next" : "s a" }, "note" : { "previous" : 60, "this" : 60, "next" : 60 }, "tempo" : 120, "strength" : 0 } } } ] }
ここまでは妥当な感じがする。
作りたいもののポエム
いきさつ
最近なにもプログラムを書いていなかった気がしてつらくなってきたので、なにか書くお題でも用意すればいいんじゃないかと思い立った。
作りたいもの
- UTAU 音源より表現力の高い音源形式
- ↑のファイル読み書き部分
とりあえず一旦ここまで書けたらいいこととする。(大きく作って死ぬことが多い気がする)
その他要件
- 既存リソースを活かすために UTAU 音源からインポートをできるようにする
- 波形情報と演奏情報とキャラクタ情報は厳密に分けて設計すること
- 欲を言えば複数音源を自在に切り替え、あるいは混ぜられるようにすること(キャラクタの枠組みを越えるべき)
ざっくりとした設計
とりあえずこんな感じでどうだろうみたいなのを書いてみる。 おそらく仕様が長大になるのでどっかで分割するべき。
{ "waves": [ { "path": "akasatana.wav", "segment": [ { "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100, "context" : { "pronounce": { "previous" : "-", "this" : "a", "next" : "k a" }, "note" : { "previous" : 60, "this" : 60, "next" : 60 }, "tempo" : 120, "strength" : 0 } }, { "begin": 500, "length": 500, "temporal_position" : 100, "front_fixed_range" : 100, "rear_fixed_range" : 100, "context" : { "pronounce": { "previous" : "-", "this" : "k a", "next" : "s a" }, "note" : { "previous" : 60, "this" : 60, "next" : 60 }, "tempo" : 120, "strength" : 0 } } ] } ] }
- begin: 開始位置
- length: 波形長
- temporal_position: ビートの位置(先行発音相当)
- front_fixed_range: 前半の固定長(固定長相当)
- rear_fixed_range: 後半の固定長
- context
- pronounce
- previous: 先発の前の発音
- this: この波形の発音
- next: 後続の発音
- note
- previous: 先発の前の音程
- this: この波形の音程
- next: 後続の音程
- tempo: 収録テンポ
- strength: 音の強さ(うーん)
- pronounce
context は分離した方がいいかもしれない。
TBD..
Qt の QUndoStack の挙動
ポエム
Qt には Undo framework があり、 QUndoStack
に QUndoCommand
を積んでいけば、いい感じに undo, redo できるようになる。
このときメモリが解放されるのかなど若干動作に癖というか、細かい部分の挙動の記述が少ないので記事にしておく。
挙動の確認は動かすのが面倒なので実際のコードを見た。ヘルプ書いてあっても英語だしあんま変わんないんだよね。
メモリ解放
QUndoStack
は以下のときにメモリ解放をしている。
push
時に、 redo 側に残されたコマンド- デストラクタ実行時に登録されているコマンド
つまり自前で QUndoCommand
のメモリ管理はせずに QUndoStack
に突っ込んでおけば良い。
push 時の挙動
確信が無かったので調べたけど、 QUndoStack
は QUndoCommand
を push
した際に一発 redo を呼んでいる。
Command と同様の操作をする必要はない。まあそれもそうか。
Qt のシグナルを一旦無効にする。
ポエム
Qt の SIGNAL/SLOT は強力なんだが、 Undo, Redo を実装しようとしてシグナル止めて無いとユーザ編集と Undo, Redo によるモデルの変更が分からなくて Undo スタックがぶっ壊れるなと思ったので一旦シグナルを止める方法を調べた。
やり方
bool oldState = checkBox->blockSignals(true); checkBox->setChecked(true); checkBox->blockSignals(oldState);
まんまや。
参考資料
スタオバさいつよ。