はじめに
「歌ったメロディや鳴った音を、その場でピアノの音に変換して鳴らしてくれるアプリを作ってみよう!」
そんな思いつきから、Claudeデスクトップで実装プランをMarkdownで書き起こし、あとはClaude Code(CLI版のClaude)にひたすらプロンプトを投げるだけで hum2piano というFlutterアプリを作ってみました。
この記事は、最初に投げた実装プランから、実機でバグを踏み抜いては直す試行錯誤まで、実際に交わしたプロンプトを時系列で並べた開発ログです。パッケージ選定で何を悩んだか、実機でしか出ないクラッシュにどう当たりを付けたか、「動いたと思ったらまだバグってた」を何度繰り返したか、AIとのペアプロの生々しい過程を残しておきたくて書きました。
- 使用ツール: Claude Code(CLI)
- 対象: Flutter(iOS / macOS動作確認、Androidは未検証)
- ソース:
record→ 自前YINピッチ検出 →flutter_midi_pro+ SoundFont → ピアノロールUI
最終的にできあがったのは、マイクに向かって鼻歌を歌うと、リアルタイムでピッチを検出してその場でピアノ音に変換して鳴らし、録音全体を音符列として解析してピアノロール風に可視化し、録音後にまとめて「演奏」として聴き直せるというアプリです。
最初に投げた実装プラン
何もないところから会話を始めるのではなく、まずClaudeデスクトップで以下のプランをMarkdownにまとめてから、Claude Codeに渡しました。技術選定の比較表や、想定される課題まで先に書き出しておくと、AIとの後のやり取りがブレにくくなる感触があります。
投げた実装プラン全文(クリックで展開)
# 鼻歌ピアノ変換アプリ 実装プラン
## 1. アプリ概要
マイクで鼻歌を録音し、音の高さ(ピッチ)とリズムを解析して音符列に変換、
それをピアノの音色でリアルタイム(または録音後)に再生するFlutterアプリ。
**コアバリュー**: 「歌った通りにピアノで鳴る」体験そのもの。
ネタ的な味付け(音痴度診断など)は後付けオプションとし、まずは変換精度を優先する。
---
## 2. 技術選定
### 2.1 ピッチ検出(鼻歌の音の高さを取る)
2案を比較。**MVPはA案(DSP)、精度に不満が出たらB案(TFLite/SPICE)へ移行**する方針。
| 案 | 方式 | メリット | デメリット |
|---|---|---|---|
| A. YIN法/自己相関法 | 信号処理アルゴリズムをDartで実装、または`pitch_detector_dart`パッケージ利用 | モデル不要・軽量・即実装可能・オフライン完結 | 精度はSPICEにやや劣る、ノイズに弱い |
| B. SPICE(TFLite) | Google製の単旋律ピッチ推定モデルをTFLite形式で実行 | 精度が高い、鼻歌のような曖昧な音程に強い | モデル変換・入出力のバッファリング設計が必要、依存が増える |
→ **結論: `pitch_detector_dart` (もしくは自前でYIN実装) から着手。**
### 2.2 音声入力
- `record` パッケージ: マイクからPCM波形をストリームで取得
- サンプリングレート: 16kHz(ピッチ検出には十分、処理負荷も軽い)
- バッファ単位: 2048〜4096サンプルごとにピッチ検出関数へ渡す(約128〜256msごとの解析)
### 2.3 周波数→音階変換
note_number = 12 * log2(f / 440) + 69 // MIDIノート番号(A4=69=440Hz基準)
### 2.4 リズム(音の長さ)検出
- 音量(RMS)のエンベロープを見て、無音区間と発声区間を分離(閾値ベースのオンセット/オフセット検出)
- 発声区間の長さを四分音符/八分音符などにクオンタイズ(BPMは固定値、例えば120から開始)
- 同一区間内でピッチが揺れる場合は中央値または最頻値を採用してノイズを吸収
### 2.5 ピアノ音源での再生
| 案 | 方式 | メリット | デメリット |
|---|---|---|---|
| A. SoundFont再生 | `flutter_midi_pro` などでSoundFont(.sf2)を読み込みMIDIノートを鳴らす | 本物のピアノ音色、和音や音の重なりも自然 | パッケージの安定性・プラットフォーム対応を要確認 |
| B. サンプル音源(wav)再生 | ピアノ単音wavをピッチシフト再生 | 実装がシンプル | 音質劣化、同時再生の管理が必要 |
| C. MIDI出力のみ | OS側の音源に任せる | 実装が軽い | プラットフォームごとに音色が変わる |
→ **結論: A案(SoundFont)を第一候補として検証。**
---
## 3. データフロー
マイク入力(record)
→ PCMバッファ(2048サンプル単位)
→ ピッチ検出(YIN/自己相関 or SPICE)
→ 周波数配列 + 信頼度配列(時系列)
→ オンセット/オフセット検出(RMSベース)
→ 音符列に変換(音名 + 長さ)
→ SoundFontプレーヤーでMIDIノート再生 / 五線譜orピアノロールUIに描画
---
## 4. 使用パッケージ候補
- `record`: マイク録音・PCMストリーム取得
- `pitch_detector_dart`: ピッチ検出(または自前YIN実装)
- `flutter_midi_pro`: SoundFont読み込み・MIDI再生
- `fftea` または `dart:math`ベース自前実装: FFT/自己相関の計算補助
※各パッケージはpub.devで最新のメンテナンス状況とプラットフォーム対応を実装前に確認すること。
---
## 5. 実装フェーズ
### フェーズ1: MVP(音が拾えて音符が見える)
1. マイク録音とPCM取得の疎通確認
2. YIN法または`pitch_detector_dart`でピッチ検出、コンソールにHz値をログ出力
3. Hz→音名変換ロジック実装、リアルタイムで画面に音名表示
### フェーズ2: ピアノ再生
4. SoundFontプレーヤーの導入検証
5. 検出した音名をMIDIノート番号に変換し、都度再生
### フェーズ3: リズム対応
6. RMSベースのオンセット/オフセット検出を実装
7. 発声区間の長さを音符の長さにクオンタイズ
8. 録音全体を「音符列」として保持し、録音後に通し再生できるようにする
### フェーズ4: UI仕上げ
9. ピアノロール風、または簡易五線譜でメロディを可視化
10. 録音→変換→再生のシンプルな3ステップUIに整理
### フェーズ5(任意): 精度向上・ネタ要素
11. ピッチ検出をSPICE(TFLite)に差し替えて精度比較
12. 「音痴度診断」「演歌変換モード」などのネタ機能を追加
---
## 9. 想定される課題
- **ノイズ・環境音**: 鼻歌は音量が小さく不安定なため、閾値調整が肝になる
- **半音のブレ**: 人間の鼻歌は正確な音程を出しにくいため、クオンタイズの丸め方の設計判断が必要
- **SoundFontのライセンス**: 商用利用可能なフリー素材を使う場合はライセンス表記を確認
- **iOS/Android差異**: マイク権限やレイテンシ特性がプラットフォームで異なるため、両方での実機確認が望ましい
このプランのポイントは、技術選定を最初から一択に決め打ちせず、A案/B案の比較表にしておいたことです。実際、この後の実装でパッケージのメンテナンス状況を理由に予定と違う選択をする場面が何度かありました。
プロンプト時系列で振り返る実装ログ
ここから先は、実際に自分が打ったプロンプトと、それに対してClaude Codeが何を調べ・何を作り・何を壊して直したかを時系列で追っていきます。
1. flutterプロジェクトを作成
プロンプト:
このフォルダにflutterのプロジェクトを作成してください
まずは空のディレクトリで flutter create するだけの最初の一歩です。ここは特に迷うところはなく、melody という名前で作成されました。
2. 実装プラン全文を貼り付け
上記のプランをそのまま貼り付けました。Claude Codeは全文を読んだ上で、いきなり実装に入らず
このプランのフェーズ1(マイクPCM取得→ピッチ検出→Hz値をコンソール出力)を、既存のmelodyプロジェクトに対して今すぐ実装開始してよいですか?
と確認を挟んできました。選択肢は「フェーズ1を実装」「パッケージ調査だけ先に」「プロジェクト名をhum2pianoに変更してから」の3つです。プランの最後にサンプルプロンプトとして書いておいた hum2piano という仮名を思い出し、「プロジェクト名をhum2pianoに変更してから」を選択しました。
ここで一度 melody ディレクトリを消して hum2piano として作り直しています。地味ですが、後から見返すとプロジェクト名を後付けで変えるコストがほぼゼロだったのはFlutterらしいところでした。
3. フェーズ1実装(パッケージ選定の分かれ道)
フェーズ1の実装が始まると、最初のプランで挙げていた pitch_detector_dart のpub.devページを確認し、こう報告してきました。
pitch_detector_dartはpub.devで最新版0.0.7が2024年4月公開で以降更新なし(2年以上メンテなし)だったため不採用。代わりにYIN法(de Cheveigné & Kawahara, 2002)をdart:mathのみで自前実装。
プランには「pitch_detector_dartから着手」と書いていましたが、実際にpub.devのメンテナンス状況を確認してから採用可否を判断するという、プランの一文(「パッケージ選定時はpub.devで直近のメンテナンス状況を確認してから採用する」)が効いた場面でした。結果、lib/audio/pitch_detector.dart にYIN法(自己相関ベースの基本周波数推定アルゴリズム)を自前実装することになりました。
record パッケージは直近リリース(7.1.1, 2026-06)だったのでそのまま採用しています。マイク権限まわり(iOS/macOS/Androidのそれぞれの設定ファイル)も一括で面倒を見てくれました。
macOSでビルド・起動して、クラッシュしないところまで確認した後、「gitリポジトリを初期化してコミットしておきますか?」と聞かれたので、Qiita化する前提もあり、はいで即答しました。以降、フェーズが進むたびに丁寧なコミットメッセージを積んでくれるようになります。
4. 先にフェーズ2の実装に着手
フェーズ2(ピアノ再生)へ進みます。ここでも同じ調子でパッケージ調査が入り、flutter_midi_pro は2026年7月10日リリースとかなり新しく活発にメンテされていたため採用しました。READMEをそのまま読み込んで、MidiPro クラスの init → loadSoundfontAsset → playNote/stopNote というAPIの流れを把握した上で実装に入っていました。
ここで問題になったのがSoundFontのライセンスです。プランにも「商用利用可能なフリー素材を使う場合はライセンス表記を確認」と書いていた通り、Claude Codeはflutter_midi_proの公式サンプルに同梱されている TimGM6mb.sf2 を見つけてきたものの、ライセンスを自分でWeb検索し、
TimGM6mb.sf2はGPL v2ライセンス。個人利用・Qiita記事化には問題ないが、将来アプリをストア公開する場合はGPLの伝播性に注意が必要。
と報告した上で、GPLの TimGM6mb.sf2 と、商用利用が明示的に許可されている GeneralUser GS(作者 S. Christian Collins)のどちらを使うか選択肢を出してきました。将来性を考えてGeneralUser GSを選択しています。ライセンス全文をそのまま assets/soundfonts/LICENSE.txt として同梱してくれました。
実機確認のフェーズでは地味に手間がかかりました。flutter build ios --no-codesign でビルドしたものはそのまま実機にインストールできず失敗し、署名付きでビルドし直したら flutter install は通ったものの、devicectl で起動すると「開発者を信頼していない」エラーが出ます。iPhone側で「設定 → 一般 → VPNとデバイス管理」から開発者を信頼させて、ようやく起動確認ができました。このあたりは完全に手作業で、AIだけでは完結しない部分(実機の物理的な操作)がちゃんと切り分けて質問されたのが印象的でした。
このコミットの副産物として、macOSデスクトップでrecordが16kHz PCM16のストリーム開始に失敗する(Format conversion is not possible)不具合も発見されましたが、flutter_midi_proの初期化有無に関わらず再現することを確認した上で「iOS/Androidが主対象なので影響なし」と切り分けてくれました。
5. flutterチーム未サポートの不具合に遭遇
プロンプト:
iOS実機でアプリアイコンをタップしても、すぐに終了してしまいます
フェーズ2が終わった直後に踏んだ、今回一番手応えのあったバグです。
devicectl経由の起動では問題なく動いていたのに、ホーム画面からアイコンをタップすると即座に落ちるという再現性の高い不具合でした。Claude Codeはまずdevicectlでプロセス一覧を確認し(過去のインストールの残骸でRunnerプロセスが3つも滞留していたのもここで発覚)、次にflutter runでワイヤレス接続を試すも「ローカルネットワーク接続の許可」待ちで止まってしまい、埒が明かないと判断しました。
ここで「クラッシュログを取得したいのでUSBケーブルで接続できますか?」と質問され、USB接続するとidevicecrashreportでクラッシュレポートを直接取得できるようになりました。実際のクラッシュログ(.ipsファイル)をJSONとしてパースし、
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Thread 0 Crashed:
0 Flutter -[VSyncClient initWithTaskRunner:callback:] + 300
1 Flutter -[FlutterViewController createTouchRateCorrectionVSyncClientIfNeeded] + 216
2 Flutter -[FlutterViewController viewDidLoad] + 396
というスタックトレースを特定しました。これをWeb検索し、Flutter本体のissue(flutter/flutter#183900)とほぼ同一のバグであることを突き止めています。ProMotion(120Hz)対応の端末で、デバッグビルドをデバッガ非接続でコールドスタートすると、エンジンの初期化が終わる前にviewDidLoadが走ってnullポインタを参照してしまう、という既知の競合状態でした。Flutterチーム自身が「デバッグビルドのコールドスタートは現状非サポート」と回答している、こちらでは直しようのない問題です。
対処は単純明快で、リリースビルド(flutter build ios --release)ならこの問題が起きないため、以降の実機確認はすべてリリースビルドで行うようにフローを切り替えています。「記録として残しておきますか?」と聞かれ、長いドキュメントではなく短いメモでとお願いしたところ、README.mdに「既知の問題」として2行×2件だけ追記してくれました。
6. フェーズ3実装
「フェーズ3(RMSベースのオンセット/オフセット検出、リズムのクオンタイズ)に進めましょうか?」に対して、はいとだけ返信しました。
OnsetDetector(RMSに2つの閾値〈on/off〉を持たせたヒステリシス方式の発声区間検出)と NoteQuantizer(実測の発声時間をBPM基準で16分音符グリッドにスナップ)という設計で実装され、検出区間内のMIDIノートは最頻値(mode)で代表値を決定してピッチの揺れを吸収するようになっています。録音した音符列をリスト表示し、「録音を再生」ボタンで通し再生するところまで一気に作られました。ここでも一区切りごとにmacOS/iOSビルド・実機インストールまで確認してからコミットされています。
7. 3連続のバグ報告 — ここが一番の試行錯誤ゾーン
実際に実機で歌ってみると、ここから3回連続でバグを報告する羽目になりました。結果的にこの部分がこの開発で一番学びの多いところだったので、少し詳しく書きます。
7-1. 連続したメロディを捉えられないです。また、再生するとそのまま再生中のままになります
原因は、音符の区切りをRMSの無音検出だけに頼っていたため、息継ぎせず連続して歌うメロディが全部1つの巨大な音符にまとまってしまっていたことでした。副作用として、その巨大な音符のクオンタイズ後の長さぶん再生がブロックされ続け、「再生中のまま」に見えていたわけです(実際には正常に、ただとても長い1音を鳴らしていただけでした)。加えて再生ループにtry/finallyがなく、例外が起きると再生中フラグが戻らない経路もありました。
対応として、発声区間中でもピッチが変化して一定時間(2バッファ≒256ms)安定して続いたら新しい音符として区切るロジックを追加しました。再生ボタンは再生中でも押せるようにし、2回目のタップで即座に停止できるようにしています。
7-2. 一声で、連続してピアノが鳴ってしまいます
7-1の修正でメロディの区切りは改善したものの、今度は逆の問題が発生しました。リアルタイム再生(歌ったその場でピアノを鳴らす機能)が、フェーズ3の音符キャプチャとは別々にバッファ単位の生のピッチ検出結果へ毎回反応していたため、1つの音を伸ばして歌っている最中もYINの微小なブレでMIDIノートが一瞬ずれると、その都度ピアノが鳴り直していました(スタッカートのように連打される状態です)。
対応として、ライブ再生とフェーズ3のキャプチャで別々に持っていた状態を1つに統合し、どちらも同じ「約256ms以上安定して変化した」という確定タイミングでのみノートを切り替えるように設計を見直しました。
7-3. まだメロディが一音一音解析されません
7-2の修正は、実は行き過ぎていました。「アクティブノートと違うMIDI値が2バッファ連続で全く同じ値であること」を切り替え条件にしていたのですが、これが厳しすぎたのです。ポルタメントや音程の微妙なブレで新しい音の検出値が61→62のように連続する2バッファで完全一致しないと、いつまでも古い音符から切り替わらない、実質的にメロディがほとんど分割されない状態になっていました。
対応として、「アクティブノートと違う値であること」だけを条件に2バッファ分の証拠を集め(値自体は毎回違ってもよい)、確定時にその最頻値を新しい音符として採用するよう変更しました。実際の音程遷移でありがちな「揺れながら新しい音に落ち着く」動きを許容しつつ、単発ノイズでの誤爆はある程度防げるバランスに調整しています。
ここまで「厳しすぎる→緩すぎる→ちょうどいい」を行ったり来たりしたのは、まさにプランの「想定される課題」に書いていた
半音のブレ: 人間の鼻歌は正確な音程を出しにくいため、クオンタイズの丸め方(最も近い半音に強制するか、揺らぎをある程度許容するか)の設計判断が必要
そのものでした。数値やロジックを先回りで完璧に決め打ちするのではなく、実機で歌って壊れ方を見てからチューニングするのが結局一番早かった、というのが実感です。
「修正されました」の一言で、この3連続バグ祭りは収束しました。
8. フェイズ4
UI仕上げのフェーズです。
PianoRollWidgetはCustomPainterでピアノロール風のメロディを可視化するもので、音程を縦軸、クオンタイズ後の拍を横軸に取り、黒鍵/白鍵の行を背景色で塗り分けています。ノートは実際の再生順(累積拍数)に合わせて隙間なく並べているので、見た目と「録音を再生」で鳴る音が一致するように設計されています。画面上部には「①録音 → ②変換 → ③再生」のステップインジケータを追加し、状態に応じて自動でハイライトが切り替わるようにしました。デバッグ用の「テスト音を鳴らす」ボタンはAppBarのアイコンに退避し、メインの操作を録音/再生の2ボタンに整理しています。
macOSでダミーの音符データを一時的に注入し、実際にウィンドウをスクリーンショットしてピアノロールの描画を目視確認してから元に戻す、という一手間を挟んでいたのも良かった点でした。
実際に使ってみて出てきた、続きの改善ラウンド
……で終わるはずだったのですが、アプリを触り込んでいると、細かい気になる点が次々出てきて、結局そのまま追加の改善ラウンドに突入しました。ここからは「フェーズ」ではなく、実際に使って気づいたことをそのつどプロンプトで投げた記録です。
9. 録音中はピアノを鳴らさない
プロンプト:
録音中はピアノの音を鳴らさないでください
それまでは録音中も歌った音がその場でピアノとして鳴る「ライブ再生」を残していましたが、使ってみるとうるさく感じたため削除を依頼。ライブ再生と音符キャプチャは元々同じ状態(_activeNoteMidi)を共有する設計だったため、ノートの開始/終了処理からplayNote/stopNoteの呼び出しを取り除くだけで、解析ロジックはそのままにピアノだけ静かにできました。ピアノが鳴るのは「テスト音を鳴らす」ボタンと、録音後の「再生」ボタンのときだけになりました。
10. 元のテンポのまま再生したい
プロンプト:
鼻歌のままのテンポで録音できますか?
RecordedNoteには元々、クオンタイズ後の拍数だけでなく実測の開始時刻(startTime)と実測長(rawDuration)も保持していたため、これをそのまま使う「元のテンポ」再生モードを追加。各ノートの待ち時間を単純に積み上げるのではなくStopwatchで録音開始からの絶対経過時間を管理し、次のノートのstartTimeまで待つ方式にすることで、処理オーバーヘッドの蓄積によるズレを防ぎつつ、フレーズ間の「間(ま)」まで含めて鼻歌そのままのテンポを再現できるようにしました。画面には「クオンタイズ」/「元のテンポ」を選べるSegmentedButtonを追加しています。
11. 検出をもっと緩く
プロンプト:
メロディの捕捉を緩めにできますか?
静かめの鼻歌や不安定な声を拾いこぼしていたようで、RMSオンセット検出の閾値(onThreshold/offThreshold)とYINピッチ検出の閾値を緩めました。トレードオフとして誤検出が増えやすくなる旨も併せて説明しています。
12. 最初の一音が録れていない
プロンプト:
最初の音が録音されてないような気がします
これはマイク/OSのオーディオセッションが録音開始直後、入力レベルが安定するまでの短いウォームアップ時間に原因があると判断。startStream()が返ってきた瞬間にすぐ「録音中」UIへ切り替えていたため、ボタンを押した直後に歌い始めるとその不安定な区間に最初の音が重なって欠けたり不安定になったりしていました。ストリームの購読自体は維持しつつ300msのウォームアップ猶予を設け、その間に届いたデータは破棄してから「本当の録音開始」とするように変更。ウォームアップ中はボタンが「準備中...」表示になり無効化されるので、いつから歌っていいか分かりやすくなっています。
13. 同じ音の連打が1音にまとまる
プロンプト:
同じ音でも、繋げることなく連続で鳴らすようにしてください
無音を挟まず同じ音程を連続で歌う(「タタタ」のような繰り返し)場合、ピッチが変わらないので1つの長いノートに繋がってしまう問題への対応です。これは7章の「ピッチ変化 or 無音」だけに頼った区切りロジックの、また別の穴でした。OnsetDetectorに、RMSエンベロープの「谷」(直近ピークの50%以下まで下がってからまた75%以上に戻る)を検出する再アタック判定を追加し、同じ音程でも再アタックがあればそこでノートを区切るようにしました。
14. オクターブがちらつく
プロンプト:
同じ周波数で1オクターブ下、または上に認識される時があります
YIN系のピッチ検出が倍音・分数調波にロックオンし、真の基本周波数の代わりにちょうど1オクターブ違いの周波数を返してしまう、いわゆるオクターブエラーです。13で緩めた閾値の副作用で起きやすくなっていた可能性を指摘した上で、キャプチャ中のアクティブノートを基準に、新しい検出値がちょうど12半音(の倍数)だけ離れている場合はオクターブ誤検出とみなして畳み込む補正を追加しました。表示中のHz値も補正後の値に合わせて再計算しています。
トレードオフとして、本当に1オクターブジャンプするメロディがあった場合はその変化が抑制されてしまいますが、鼻歌でのオクターブジャンプは比較的稀という前提でのバランス調整です。
15. 緩めすぎた閾値を少し戻す
プロンプト:
閾値緩和を少し厳しくしてください
13で緩めすぎた閾値がオクターブ誤検出などの誤爆を誘発していたため、ライブラリのデフォルト値と13での緩和値のちょうど中間くらいまで戻して着地させました。
できあがったものの全体像
自分で一度録音してみましたが、あまりの不協和音の連発でアプリがバグっているかと思いましたが、ピアノアプリで試したところ正常でしたので、ただ自分が音痴なだけでした。。。
前半:他の端末のピアノアプリから音を出して録音
後半:ピアノ音に変換して再生
(後半から音が鳴ります)
データフロー
ディレクトリ構成
lib/
main.dart
audio/
mic_recorder.dart # record のラッパー
pitch_detector.dart # YIN法によるピッチ検出(自前実装)
onset_detector.dart # RMSヒステリシスによる発声区間検出
music/
note.dart # 音符データクラス RecordedNote
note_converter.dart # Hz -> MIDIノート番号 -> 音名
note_quantizer.dart # リズムのクオンタイズ
playback/
piano_player.dart # flutter_midi_pro のラッパー
ui/
recording_screen.dart # 録音/変換/再生の3ステップ画面
piano_roll_widget.dart # CustomPainterによるピアノロール
使用パッケージと採用理由
| パッケージ | バージョン | 採用理由 |
|---|---|---|
record |
7.1.1 | マイクPCMストリーム取得。2026年6月末リリースで活発にメンテ |
flutter_midi_pro |
4.0.4 | SoundFont再生。2026年7月10日リリースと最も新しい |
| ピッチ検出 | 自前実装 |
pitch_detector_dart(0.0.7、2024年4月から更新停止)は不採用、YIN法をdart:mathのみで自前実装 |
| SoundFont | GeneralUser GS | 商用利用・再配布が明示的に許可されたライセンス。GPL v2のTimGM6mb.sf2は将来のストア公開を見据えて見送り |
既知の問題
READMEに残した2件のメモそのままです。
macOSでは、recordが16kHzストリームを開始できません(Format conversion is not possible)。macOSデスクトップ限定の問題で、主対象のiOS/Androidには影響しない想定です。iOSでは、ProMotion端末でデバッグビルドをホーム画面から直接起動するとクラッシュします(flutter/flutter#183900)。Flutter本体の既知バグで、リリースビルドを使えば回避できます。
まとめ
最初に技術選定の比較表つきプランをMarkdownで書いておいたことで、Claude Codeが「プランに書いた通りに素直に実装する」だけでなく、pub.devのメンテ状況やライセンスを都度自分で調べた上で、プラン通りにいかない判断を選択肢付きで確認してくるという進み方になったのが今回一番よかった点でした。
一方で、実装した瞬間に完璧に動くことはほとんどなく、実機で歌ってみて初めて「連続したメロディが1音にまとまる」「一声伸ばしただけで連打される」「今度は逆に分割されなさすぎる」という具合に、閾値やデバウンスのバランスを行きつ戻りつ調整する必要がありました。この試行錯誤の過程こそが、DSPベースのピッチ検出でリアルな人の声(しかも「鼻歌」という不安定な入力)を扱う上でのリアルな難しさだったと思います。
頑張ればカラオケアプリも夢ではないかもです!