この文章は
SESSIONSアドベントカレンダー2024、10日目の記事です。
現在作成中のソフトウェア・Re:codeのSESSIONSに向けた開発スケジュールについて書いていきます。
今回余裕をもった(持たざるを得なかった)スケジュールなので、社会人の人とかがコンペ提出のための作品作るときの参考になれば幸いです。
Re:codeについて、概要やサポートページも用意していますので良かったら御覧ください。
こちらの方に思想やできることを書いてます。
https://qiita.com/MachiaWorx/items/64d951c89df23f7e6e92
https://machiaworx.net/recode/doku.php?id=start
開発経緯(かんたんに)
大前提として、開発経緯を簡単に記載します。
- 自身の腱鞘炎に伴い、マウスを使わない作曲ツールが欲しいので作った
- 最初Unityベースで作っていたが一部機能が実現できないため開発中止
- 問題点をクリアできるよう再開(作り直し)の準備をしていた
SESSIONS開催までの開発期間
だいたい5ヶ月。
その間まったく作業できない時期が存在するので実際の開発期間はもっと短いです。
大まかなスケジュール
6月下旬~7月:必要な機能を実装済み
8月~10月中盤:大きな機能の実装はほぼ手つかず、デバッグや動画撮影に備えた利用ソフトウェア準備等がメイン
10月後半:動画撮影・提出
11月前半:デバッグ
11月中盤:ソフトウェア公開
ゴール
- SESSIONSへの動画提出
- Re:codeソフトウェアの公開(SESSIONS参加と同時に公開を見込んでいた)
スケジュール詳細
6月以前
色々あって開発中止してたRe:codeをどう実装しなおせばいいか等はある程度情報を仕入れてた。
6月
2024/6/7にSESSIONSの告知あり。
これをトリガーに開発再開した。
6/27頃から開発開始。
利用するライブラリを選定してテスト実装を行う。
同時にGUI・発音トラック数を定義して、音声出力の実装まで行う。
以前からどういうライブラリを使えばいいかだいたいの当たりを付けていたため、上記作業はそれほど困ることなく進んだ。
以前、メガデモ用にGLSLでグラフィック編集・作曲するためのツールを作成していたので、当該プログラムの構成を流用する形で対応。
よってdear ImGUIを継続利用。
サウンドIOについては一時期波形メモリ音源等独自にシンセサイザーを作っていた関係で、ある程度のノウハウはあったため実装には困らない。
ただ、Re:codeの再生に今後課題が出ることを懸念しライブラリ側に改造を施した。
7月前半
前半で内部の構成を決定、実装まで行う。
ファイル読み込み・コンパイル機能・関数作成まで組み込み済み。
MiniScriptのContext(文法処理クラス)について、そのまま変数を避難しようとすると正常にアクセスできないことを確認した。
幸い公式Discordにて同様の質疑が行われていたのでそれを参考にして、変数を格納するだけのContextインスタンスを作成し更新するようにした。
7月中盤
中盤からMML入力を作成開始。
元々譜面として配列に情報を入力することだけを考えていたが、音楽に詳しい人にも使ってもらうことを考えると、現行の仕様はなかなか辛いものがある。
ということで、文字列を配列に変換するという位置づけでMMLを記述できるようにした。
インタプリタに近い形での実装が必要になるため、そんなの作れるのか?と不安になったが、意外とどうにかなった。
同じく中盤でMIDI出力も実装済み。
いくつかのライブラリをお試し実装してみて、使い方もシンプルそうなPortMidiを選択。
GUI周りの問題が出たため、ラジオボタンの形でMIDI出力先を選択できるようにした。
同じく中盤からホットキーの入力について実装を進め始める。
最初DLLを用いてキー入力をインタラプトする処理を実験的に書いたが、これだと「キーがきかない!」という問い合わせ来るだろうなと思って初期バージョンへの組み込みはとりやめ。
当時の情報:
https://machiaworx.net/diary/doku.php?id=2024:07:17
7月後半
後半は、MML処理の細かい部分の詰め・MIDI再生タイミングの詳細化・発音タイミング制御機能追加を実装。
上記の時点で発音タイミング制御の一環として、MIDI再生をマルチスレッド実行で制御してみることにした。実装自体は早々に終了。
ただMIDI周りでWav再生とタイミングを同期できず、再生についてもスケジュールからの乖離が発生したため、マルチスレッド処理は取りやめ。
Callback書き込み時にMIDIデータを書き込む際に再生タイミングを同期するようスケジューリングする実装で処理することにした。
後半の時点で言語を制御するVMを二重化した。
読み込み中に書き込みが必要なため、その際にデッドロックやメモリ違反が発生しないようにすることが目的。
再生時ノイズが発生し始めた。
確認したところ、コマンドラインによる出力によって発生していることが発覚。
これは、IOを切り替える処理はそれなりの重さになる模様。また、Callbackから出力するPrintfの頻度が高すぎるのもある。
結果としてCallback関数内でコマンドライン出力の処理を呼ぶと、時たまノイズが発生する。
この時点でコマンドラインによるメッセージングは全部デバッグ用の出力とすることに決定。(そもそもコマンドラインは表示しないことにした)
#ifdef ディレクティブで出力し、最終的な出力はウィンドウ内だけに収めるようにした。リリースビルドではコマンドライン出力なし。
メッセージング処理自体も軽減し、Callbackでデータ書き込みを行う頻度を調整済み。
8月
仕事とイベント準備に時間を取られたため、大きく進捗はなし。
ただ少しの機能追加・デバッグと動画に利用するソフトウェア・リソース準備等はできそうだったので、一部進めることにした。
8月時点でMIDI機能・シンセサイザー機能(単純波形)・サンプリング再生については実装済み。
9月も業務・イベントによる繁忙により実装追加が困難な見込みのため、動画に録画するための実装・準備はほぼ終了として、実装済みの内容から逆算して動画構成について考え始める。
9月
仕事が忙しいためソースコードにはあまり触れず。
中盤にソースコードを触る。MIDIのVelocity反映が必要として実装開始。
提出した動画では使わなかったものの、今後に大きく役立つ内容となった。
10月
別の開発作業がメインだったため、Re:codeのソースコードにはあまり触れず。
後半2週程度で動画として録画する内容をテキストにまとめる作業を実施。
自分が即興で何かするとろくなことにならないという経験から、基本方針と記述内容を決め打ちすることにした。
それほど凝った動画も作れないと思ったため、以下方針で動画を作成。
- ソースコードが見えるようにする
- コンパイルタイミングも見えるようにする(Re:codeは画面に収める)
何度か試しに録画して、入力に詰まった内容を台本から修正の上、録画内容を詰めていく。
最初の1週で方法確認・ソフトウェアの準備と録画内容の整理、残り1週で実際に録画をして内容修正していった。
最終日1日前くらいに提出完了。
11月
動画撮影時に残っていたバグがあったので修正。
具体的には、「一度譜面を登録する関数を使った際、取り除いてコンパイルしたタイミングでエラー出力されるケースがある」処理を修正。
必ず発生しないのは、二重化したContextの切り替えについてうまくいってないケースがあったため。よって、Contextの切り替え条件を明確化し、再生するContextと更新されるContextを同期するよう調整。
SESSIONS当日、手元でRe:codeを動かそうと思ったら謎のバグで強制終了発生。
ソースコード一式を持っていたので、会場でVisualStudio諸々を準備してデバッグしてた。
セミナー1回目が終了するくらいで、ファイル名の指定方法に問題を確認、書き換えてデバッグ。
帰宅後、上記の内容を制作中のソースコードに反映し、公開準備完了。
SESSIONS終了後、ソフトウェア公開も完了。
別途サポートページも作成済み。
ここで定義していたゴールをすべて達成。
書き出してみて思った事
当初開発規模に対してバッファを取った形で「9月にプログラムが動くようにする」「10月に録画、10月中に提出」というざっくりした想定でスケジュールしてましたが、仕事が想定以上に忙しくなったので、正解だった模様。
最初からスケジュールを構築してタスク処理できればベストとは思いますが、他要因でタスクが処理出来ない場合も想定し、スケジュールを適時更新して「Max100%として、デッドラインにはどのくらいの完成度になる想定で」作っていくしかないのかなと思いました。
当初8月・9月も作業想定でしたが、上記の通り仕事と別作業のため、Re:codeの作業は実質0になってました。
このため、8月時点でシンセサイザー機能については動画には採用せず、MIDI機能のみで作成することを決めてます。
まとめ
Re:code開発スケジュールについて書き出しました。
作業ができない場合に備え「最初はスケジュールをゆるく見積もって(何月時点でどういう状態になってる、くらいの粒度を書き出せればベスト)、適時更新・詳細化する前提にする」「Maxどのくらいの機能があって、スケジュール更新時どのくらい達成できるかを明確化していく」ことが必要。