Skip to content
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

[project-s]再生周りの機能を追加 #1184

Merged
merged 12 commits into from
Mar 1, 2023

Conversation

sigprogramming
Copy link
Contributor

@sigprogramming sigprogramming commented Feb 6, 2023

内容

以下の機能を追加します。

  • 位置(ティック)と時間(秒)を相互に変換
  • 再生・停止(スケジューリング)
  • 再生位置を表示(分 : 秒 . ミリ秒)
  • 音量を設定
  • 動作確認のためにシンセで簡易的に再生(編集時に反映)

また、以下の不具合を修正しています。

  • 先頭のテンポ・拍子を削除した時にデフォルト値が追加されない不具合

もう少し細かくPRすることも考えましたが、動作確認できた方が良いかもと思い、この範囲でPRしています。
(1000行超えました…すみません…)

Web Audio APIをラップするライブラリを利用することも考えましたが、曲中でのテンポ変更や指定した位置からの再生、ループ再生などがうまく実装できなかったので、とりあえず自前でラッパー(レンダラー)を実装しています。
もしライブラリを利用して実装できそうであれば後でライブラリに置き換えられればと思っています。

設計について

基本的にストアのステートを元にレンダラーで再生を行う形で、なるべく「ストア→レンダラー」の一方向になるようにしています。(レンダラーから取得するのは再生位置のみ)

再生位置は頻繁に更新されるので、とりあえずストアには置かず、再生時にgetterを介してポーリングする形にしています。(ポーリングは一箇所で行うようにした方が良いかもなので、後ほど考慮できればと思います)

また、再生位置やノートの位置は、時間(秒)に変換してからレンダラーに渡すようにしています。この形にしたのはレンダラーの処理を簡単にするためですが、ストア側が少し冗長になってるかもしれません…

Scoreについて

(PRとあまり関係ないですが、実装中に少し悩んだので)

現状onMountedでscoreなどのステートの初期化を行っているので、各UIでscoreを取得する際にundefinedでないかチェックする必要があります。
actionではとりあえず関数でチェックして取得する形に変更しています。

scoreのチェックを減らすには、UIがマウントされる前にscoreを初期化するようにして、scoreが存在する前提のUIでは「存在をチェックするgetter」を介して取得するようにするか、任意のタイミングで初期化を行わずに最初からscoreを設定するようにした方が良いかもと思いました。(他に良い方法があればご提案いただけますと幸いです)

関連 Issue

ref #1041

その他

  • 音声データを再生する機能はPRを小さくするために一旦削除しています
    • 音声データはノートと同じようにイベントとして扱う形を考えています
  • Web Audio APIのラッパー(レンダラー)は、とりあえずAudioRendererという名前でinfrastructureディレクトリに置いています

@romot-co
Copy link
Contributor

romot-co commented Feb 8, 2023

@sigprogramming
ありがとうございます!すごいです
こちら確認中ですが、少々お時間いただきそうです!

取り急ぎScoreについて

実装いただいた方法で大丈夫そうに思えます!

ほか少しだけ考えてみたのですが、Scoreoptionalになっている理由が無い?ような気がするため、
初期stateで持たせておいても(tsエラーが出なくなるだけで安全かは微妙ですが)良い気がしました…!

なにか理由あったかも&より良い方法がないか確認いたします!

type.ts

export type SingingStoreState = {
  ...
  score: Score; // optional外す
}

singing.ts
undefinedでなく初期指定(asはいらないかも)

export const singingStoreState: SingingStoreState = {
 ...
  score: {
    resolution: 480,
    tempos: [] as Tempo[],
    notes: [] as Note[],
    timeSignatures: [] as TimeSignature[],
  } as Score,

@sigprogramming
Copy link
Contributor Author

sigprogramming commented Feb 8, 2023

@romot-co ご確認ありがとうございます!
プルリクが大きくなってしまいすみません。。

Scoreについてありがとうございます!
optionalになっているのは、#970 でストアを実装した際に、Scoreオブジェクトの作成が複雑になりそうに感じ、後で作成&設定できるようにしたためですが、おっしゃる通り初期stateで持たせて良さそうです…!(コードありがとうございます!)

Copy link
Member

@Hiroshiba Hiroshiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!

すげーーーーーーーーーー!!!!!!!!
サクサク動きますね、感動しました!!

いくつかコメントしていますが、どれもsuggest程度で必須級ではないかなと思います。
ガシガシ実装していって頂ければ・・・!!!

あと、正直言うとAudioRenderer周りは雰囲気眺めただけです・・・!
クラスごととかに役割などをちょっとだけコメントドキュメント残しておくと、将来誰かの役に立つかもと思いました・・・!

src/components/Sing/ToolBar.vue Outdated Show resolved Hide resolved
src/store/singing.ts Outdated Show resolved Hide resolved
@Hiroshiba
Copy link
Member

Hiroshiba commented Feb 26, 2023

あ。scoreに関して、同じく最初からstoreに代入でもいいかなと思いました。
EMPTY_SCOREの中身を取り出してgenerateEmptyScoreみたいな関数を作り、stateをそれで初期化、EMPTY_SCORE内でgenerateEmptyScoreを呼ぶ感じを想像しています。

singChannelもundefinableなので毎回チェックする必要があって大変ですが、まあ仕方ないかなと思いました。
開発中ですし、面倒であれば無理やり迂回しても良いかもです。こんな感じで。

let singChannel: SingChannel = undefined as any as SingChannel; // FIXME: あとで消す

@sigprogramming
Copy link
Contributor Author

@Hiroshiba
レビューとscoreについて、ありがとうございます!
おっしゃる通り、空のscoreを作成する処理を関数にして、stateをそれで初期化する形にすると良さそうです。
score周りを整理するPRを作成し、そちらで行いたいと思います。
singChannelやtransportはひとまず毎回チェックする形にしました。

@romot-co
Copy link
Contributor

romot-co commented Mar 1, 2023

@sigprogramming
LGTMです!ありがとうございます!
中身完全に見られていないのですが、動作すること確認しました!

@sigprogramming
Copy link
Contributor Author

@romot-co
ご確認ありがとうございます!
こちら、少しリファクタリングと修正を行ってからマージしたいと思います!

@sigprogramming
Copy link
Contributor Author

マージします!

@sigprogramming sigprogramming merged commit 7bce3e3 into VOICEVOX:project-s Mar 1, 2023
@sigprogramming sigprogramming deleted the audio_playback branch July 25, 2023 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants