-
Notifications
You must be signed in to change notification settings - Fork 308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
選択した再生デバイスがソングでも適用されるようにする #2375
Conversation
🚀 プレビュー用ページを作成しました 🚀 更新時点でのコミットハッシュ: |
たぶんAudioContextの内部でエラーが出ているので、catchは難しそうですね…
音声グラフを構築する処理がまだ全然整理できていないので、関連オブジェクトの再生成は難しいかもです。 |
そうですね。一旦接続解除のことは考えずに進めようと思います。
|
AudioContext.sinkIdについて処理ごとに設定していたのを、読込時と設定変更時に設定するようにしました。こちらのほうが設定漏れが起きづらいかなと。ただし接続解除については考慮していません。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
シンプルなコードで良い感じの雰囲気ですね!
エラーメッセージもトーク側と揃えていただいててありがたいです!!
今設定時に変更する形になっていますが、再生時に設定する形にするとよりシンプルになりそうだなと感じました!!
(2箇所にあるapplyDeviceId
が1箇所になるはず)
あとInstrumentにあるaudioContextにsetSinkIdするのではなく、直接AudioContextにsetSinkIdするとシンプルになるかも・・・・・・?
(別のAudioContextなんでしたっけ。。。)
再生関数はSING_PLAY_AUDIO
かな。
ここでaudioContext.setSinkIdする感じのイメージです!!
src/store/singing.ts
Outdated
@@ -551,6 +551,7 @@ let clipper: Clipper | undefined; | |||
// NOTE: テスト時はAudioContextが存在しない | |||
if (window.AudioContext) { | |||
audioContext = new AudioContext(); | |||
// 読込時にここでAudioContextにsetSinkIdできると簡単かつ確実だけど... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
メモ消し忘れかも?
// 読込時にここでAudioContextにsetSinkIdできると簡単かつ確実だけど... |
音声信号を定期的にバッファに書き込む処理がChromiumにあると思うのですが、たぶんそこでエラーが起こっているので、回避は難しいと思います…! |
…nto selection-unify
設定をコンポーネントからsinging.tsに移しました。ソング関連の音が出る操作で把握してるのは、 b.再生中に最初に戻る c.再生中にクリックで再生位置指定 d.ノートを打ったときのシンセ音 e.(ノートを打って音声生成前に再生した場合はdから始まって、準備できたら自動でaに切り替わる?) の5つです。audioRendering.tsでやろうとすると引数で運ぶのがややこしくなりそうなのでsinging.ts内の3箇所で設定しています。 |
src/store/singing.ts
Outdated
const applyDeviceId = (device: string) => { | ||
if (transport && previewSynth) { | ||
transport.sinkId = device; | ||
previewSynth.sinkId = device; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ちょっと頓珍漢なこと言ってるかもなのですが、ここでaudioContext.setSinkId()するのってできたりしますか? 👀
これができればPolySynth
とTransport
側のset sinkId
をなくせるな~~~と思ってます!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3箇所にコード実装なるほどです!!!
すみません、気づいてなかったのですが、もしかして再生中にsetSinkIdできるのでしょうか 👀
再生中に変更しても問題ないのであれば、設定をwatchする方法で今までの全問題を解決できるかもです!!
たぶんですが、App.vueにこんな感じのコードを書けば良いはず・・・!
useWatchEffect(()=> {
applyDeviceId(state.savingSetting.audioOutputDevice);
})
(起動直後とstate.savingSetting.audioOutputDevice
が変更されるたびにapplyDeviceId
が呼ばれる・・・・はず!)
動きますね。盲点でした。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ほぼLGTMです!!!
変更ありがとうございました!!
src/store/singing.ts
Outdated
// AudioContextに再生デバイスのIDを設定 | ||
const applyDeviceId = async (device: string) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この関数自体をAPPLY_DEVICE_ID
内に移してあげるとよりコンパクトかもと思いました!
トーク側はPLAY_AUDIO
内に書かれていたので、雰囲気も揃ってメンテナンスしやすいかも。
src/store/singing.ts
Outdated
@@ -1682,6 +1698,12 @@ export const singingStore = createPartialStore<SingingStoreTypes>({ | |||
}, | |||
}, | |||
|
|||
APPLY_DEVICE_ID: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ソング側であるということが若干分かりにくいので、後ろにTO_AUDIO_CONTEXT
とか付けてあげるのどうでしょう?
src/components/App.vue
Outdated
watchEffect(() => { | ||
store.actions | ||
.APPLY_DEVICE_ID({ device: store.state.savingSetting.audioOutputDevice }) | ||
.catch((e) => { | ||
console.error(e); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここはそのままエラーになって大丈夫です!
(そのエラーが最終的にログに吐き出されます)
なので単純にvoid store.actions.APPLY_DEVICE_ID({ device: store.state.savingSetting.audioOutputDevice })
として良さそう?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!!!
とてもスリムな実装になりましたね!!!
お付き合いいただきありがとうございました!!!
あとちょっとだけメンテナ的に変更したいところがあるので、こちらで微調整させていただこうと思います!
またもしよかったらプルリクウェルカムです!!
こちらのコメントに書いた他のおすすめとかまだまだありますので、ぜひ・・・!!
内容
再生機器のソングへの適用自体はAudioContext.setSinkIdでデバイスIDを渡すだけでよかったのですが、デバイスの接続が切れるとかなり厄介ですね。AudioContext(たぶん)が「The AudioContext encountered an error from the audio device or the WebAudio renderer. localhost/:1」を投げて動かなくなります。
理想としては接続が切れたら、
再生中なら停止 → 再生デバイスがデフォルトに戻ったことをユーザーに通知 → 操作を続行できる
としたいかなと思いますが、特定の処理で起こるわけではない(接続が切れた時点でエラー発出)のでcatchが難しいのと、AudioContextを初期化すると関連オブジェクトも再生成しないといけないのとで、どうしようかなあという状況です。
関連 Issue
#2300