ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
RealityKitオーディオで空間コンピューティングアプリの質を向上
RealityKitオーディオを使用して、空間コンピューティング体験を向上させましょう。空間オーディオにより、イマーシブな3D体験がどのように実現されるかをご紹介します。環境音やリバーブから、3Dコンテンツに個性を加えるリアルタイムの音声手順ガイドまで、アプリをより魅力的にするRealityKitオーディオAPIについて詳しく説明します。
関連する章
- 0:00 - Introduction
- 2:01 - Spatial audio
- 11:43 - Collisions
- 16:57 - Reverb presets
- 18:24 - Immersive music
- 20:41 - Mix groups
リソース
関連ビデオ
WWDC24
-
ダウンロード
こんにちは RealityKit AudioチームのJamesです 今日は 新しいRealityKit Audio API についてお話しします これにより 空間コンピューティングの体験が よりインタラクティブで イマーシブなものになります 同僚のYidiは 現実環境にいながら 仮想宇宙船を飛ばすゲームを 開発しています しかも 現実環境だけでなく カスタム仮想環境でも さらにはポータルを通じて 宇宙空間にも飛び込めるのです このアプリでは 新しい SpatialTrackingService APIを使って 手の動きをなめらかにトラッキングし 宇宙船を操縦します
さらに フォースエフェクトのような 新しい物理的機能を使用して 徐々に難度が増す小惑星群が 作り出されます
そして 貴重な貨物を運ぶトレーラーを 取り付ける物理ジョイントを使って 激しく飛ぶと 揺れ動くようにすることができます また 新しいポータル クロッシングコンポーネントを使って ポータルを通じて宇宙船を 宇宙空間に出入りさせることができます
これらの新機能のそれぞれが バーチャルとリアルの間で ダイナミックな 相互作用を生み出します
このゲームの構築方法について詳しくは 「Discover Reality Kit APIs for iOS, macOS, and visionOS」 のセッションをご確認ください このセッションでは RealityKit Audioのパワーを使って ゲームをさらにイマーシブで インタラクティブなものにしていきます 具体的に見ていきましょう
このセッションのリンク先から サンプルプロジェクトをダウンロードできます まず 音声ファイル再生と リアルタイム生成オーディオを使って 宇宙船に空間オーディオを追加します 次に バーチャルオブジェクト間や バーチャルと実物のオブジェクト間の 衝突音に 空間オーディオを追加します それから リバーブを追加して イマーシブ環境を作り 宇宙船と一緒に ユーザーを新しい空間にいざないます そして 音を再生する環境音を使って 雰囲気を設定します 最後に ユーザーが オーディオミックスグループを使って 好みに応じて 音を調整できるようにします では まず宇宙船自体の オーディオから始めましょう 宇宙船には視覚を反映した 多層のサウンドデザインがあります
2つのエンジンが搭載されており 各エンジンには蒸気跡 排気装置 そしてタービンがあります 視覚的には 蒸気跡は スロットルの高さに かかわらず放出され 排気装置はスロットルが 上がるにつれて長くなります タービンは宇宙船の本体に 収められているため 視覚的には見えませんが 音のデザインを使って 見えない部分を 表現することができます 蒸気跡には 柔らかいノイズ音を再生し スロットルの高さにかかわらず 一定の音量を保ちます 排気装置には スロットルが上がるにつれて 音が大きくなる 強力なノイズ音を再生します タービンには スロットルに依存したパラメータを持つ 動的に生成された音を再生します ちょっと聞いてみましょう
最初に 蒸気跡のオーディオ再生です 反対方向に回転させると 少し静かになり 音が暗くなります 次に排気装置をオンにして スロットルを操作します スロットルが上がるにつれて 音が大きくなるのがわかります
この仕組みをコードで見てみましょう
アプリのバンドルから蒸気跡の オーディオファイルをロードします そしてEntity.playAudioを使用して すぐにエンジンエンティティから再生します
RealityKitのオーディオ再生は デフォルトで空間的です わずか数行のコードで オーディオが6つの自由度で レンダリングされ 自分や音源が動いたり回転したりすると そのレベルとトーンが更新されます 物理ベースの距離減衰があり 音源が離れると 自然に音が小さくなります
最後に 空間オーディオの音源には リバーブが適用され 現実環境から リアルタイムでシミュレートされます
注意点として 空間オーディオで再生される音は 空間化される前にシングルモノチャンネルに ミックスダウンされます 予期しないミックスダウンの アーティファクトが 空間レンダリングに追加されないよう モノファイルを作成することをお勧めします
蒸気跡のオーディオファイルは短く シームレスにループするよう作成されており ポップやクリック音がありません AudioFileResource.Configurationの shouldLoopプロパティを設定すると この短いファイルを 連続的な ノイズ音であるかのように再生できます
同じ短いループファイルを 両方のエンジンから再生します shouldRandomizeStartTime プロパティを設定して 両方のエンジンが音を出すときに ファイルの異なる位置から 再生を開始します ループと再生開始時刻のランダム化の 組み合わせを使用することで リソースを効率的に利用しながら 豊かなオーディオ体験を提供できます ノイズの蒸気跡のオーディオファイルは シームレスにループするよう作成されており つまり 突然開始されます オーディオ体験を高めるため オーディオをフェードインさせてみます Entity.playAudioメソッドから返される AudioPlaybackControllerを保持します
AudioPlaybackControllerは 特定のサウンドイベントインスタンスの リモートコントロールのようなもので エンティティから再生される AudioResourceのインスタンスです Entity.playAudioまたは Entity.prepareAudioを呼び出すたびに AudioPlaybackControllerが返されます これを保持して 設定や 再生 ポーズ 停止などの トランスポートコントロールに使用できます ゲインを-.infinityに設定します AudioPlaybackControllerの ゲインプロパティは 相対的なデシベル単位であり -.infinityは無音 ゼロは名目上の音量です すべての音は最大ゼロデシベルに 制限されています
次に AudioPlayback Controller.fade (to:duration:)メソッドを呼び出し 1秒でゼロデシベルにフェードインさせます
蒸気跡のオーディオは再生されていますが 宇宙船を飛ばすときは 自然でダイナミックな音にしたいですよね 例えば 宇宙船がエンジンを こちらに向けている場合は エンジン音を細かく聞きたくなりますが エンジンが背を向けている場合は 音を抑え 暗くする必要があります エンジンの空間レンダリングは SpatialAudioComponentと 指向性で指定します
まず 新しいEntity()を追加し これをaudioSourceとして表現します 次に これをエンジンの子として追加します それから エンジンではなく audioSourceからオーディオを再生します
audioSourceエンティティに SpatialAudioComponentを設定し SpatialAudioComponentの 指向性を フォーカス0.25のビームパターンに 設定します 指向性は 空間オーディオの音源からの 音のプロパゲート方法を定義します ビーム指向性パターンは 0から1の範囲で動作し 0は全方向性 つまり すべての方向に同じトーンで 音がプロパゲートし 1は音の後方が 前方よりも静かで暗くなる タイトなビームパターンになります
最後に 音がエンジンの排気装置から出るように audioSourceを回転させます これで 船が回転すると 音のレベルとトーンが 変化するのが聞き取れます
SpatialAudioComponentを使うと 空間オーディオの音源の 指向特性を指定できます また エンティティから発生する すべての音イベントの音量を設定できます Componentプロトコルに準拠しているため SpatialAudioComponentを使うと カスタムシステムのコンテキストで 動的に音源の音量を 簡単に操作できます 例えば 単一のスロットル値が 宇宙船の物理 グラフィックス オーディオを左右します エンジンの排気音は スロットルが0のとき無音で スロットルが1のとき最大音量になり その間の中間値が なめらかに計算されます カスタムオーディオシステムが 更新のたびにスロットル値を読み取り 線形スロットル値から 対数デシベルに値をマッピングし SpatialAudioComponentの ゲインプロパティを デシベル値で更新します 宇宙船のオーディオ実装は さらにダイナミックなものに進化してます 宇宙船が飛ぶと 指向性パターンによって 音量とトーンが変わるのが聞こえます スロットルが上がったり下がったりすると 排気音が大きくなったり小さくなったりします 青い光とノイズの背後には 一対のタービンがあります 目には見えませんが スロットルが上がったり下がったりすると 速く回転したり 遅くなったりするのが聞こえます
Hangarビューで 宇宙船の タービンを回して その音を聞いてみましょう スロットルに合わせて音の周波数が 変わるのに注目してください
これをコードでどのように 実現するか見てみましょう
エンジンの一つを表すエンティティを 引数に取るメソッドから始めます 次に Entity.playAudioメソッドの バリアントを呼び出します このエンティティから音源を 再生するのではなく コールバックを提供し オーディオシステムによって表示される バッファに直接サンプルを書き込みます このバリアントのEntity.playAudioは AudioGeneratorControllerを返します オーディオがストリーミングを続けるには アプリがこれを保持する必要があります
AudioGeneratorControllerで 書き込まれたオーディオバッファは エンティティで再生される オーディオリソースと同じように動作します 再生はデフォルトで空間的ですが エンティティ上の空間オーディオ 環境オーディオ チャネルオーディオの コンポーネントを設定し バッファのレンダリングを コントロールすることができます これは オーディオファイルの再生と 同じように行うことができます
アプリには AudioUnitTurbineという カスタムaudioUnitがあります このAudioUnitには Objective-Cインターフェイスがあり そのレンダーブロックには リアルタイムセーフなコードがあります AudioUnitTurbineは 0から1の範囲の 単一のスロットル値を持ち audioUnitの実装は この値を使って 複数のオシレーターを駆動します まず オーディオユニットを インスタンス化します 次に AudioGeneratorControllerの設定を 準備します その後 audioUnitの出力の フォーマットを作成し それを audioUnit.outputBussesに 設定します audioUnitのレンダーリソースを 割り当て audioUnit.internalRenderBlockを キャプチャします 次に AudioGeneratorControllerを オーディオジェネレータの設定で構成します
最後に audio generatorの コールバックで提供された オーディオデータに対して audioUnit.internalRenderBlockを 呼び出します
AudioGeneratorControllerを使用した リアルタイムオーディオは Appleが提供するオーディオユニット 自作のカスタムオーディオユニット または自作のオーディオエンジンの出力から オーディオをパイプすることができます オーディオは RealityKitやvisionOSが提供する レイトレース空間オーディオによって レンダリングされます どのように作成したサウンドも システムの他のサウンドと一貫した 共有スペースおよび 混合スペース 段階的なイマーシブスペース フルイマーシブスペースで 音響効果を受けます
RealityKitでのオーディオ再生は デフォルトで空間的であり 私たちはデフォルトの動作を できるだけ自然にするために 多大な労力を費やしています もちろん 私たちの宇宙船は 現実と魔法の間を飛び回るので 物理学の法則を少し いじることもできます 例えば 宇宙船が 私たちの近くを飛んでいるとき キャビンから静かに 音楽が流れてくるのが聞こえます ちょっと聞いてみましょう
このオーディオトラックを デフォルトの 空間オーディオコンポーネントの パラメータで再生すると 常にステレオの再生が聞こえます 空間オーディオコンポーネントの 距離減衰をカスタマイズすることで 望む効果を得ることができます
距離減衰をカスタマイズすることで 特定の音が 音源に非常に近い場合にのみ 聞こえるようにすることができます あるいは 遠くにいても 音が聞こえるように カスタマイズすることもできます rolloff factorが1の場合 空間オーディオとして自然な速さで減衰し rolloff factorを2に設定すると 音が自然の速さよりも 2倍の速さで減衰します rolloff factorを0.5に設定すると 音が自然の速さの 半分のスピードで減衰します では オーディオの距離減衰を 設定してみましょう
ここでは rolloff factor 4で distanceAttenuationを設定し 宇宙船が非常に近くに 来たときにのみ特定の音が 聞こえるようにしましょう この空間オーディオの音源の ゲインを下げて 宇宙船が非常に近くに来たときにのみ その音が聞こえるようにします 次に コンテンツ内のエンティティが 衝突したときに音を発する方法を 見てみましょう まず 聞いてみましょう 宇宙船が コンクリートの床や 木箱 金属の梁 またはガラスと 衝突する音を聞いてみます
宇宙船は 例えば小惑星などの 動くバーチャルオブジェクトや セメントの床 木製の立方体 Studio環境の金属の梁など 静的なバーチャルオブジェクトと 衝突するかもしれません 混合現実環境では 宇宙船が 周囲の実物から再構築された メッシュと衝突する場合があります これらの衝突を よりインパクトのあるものにするために アプリの物理的な素材から得られた 情報を基にしたオーディオを統合します
まず CollisionEventsに 応答する必要があります .Began衝突イベントを処理する メソッドを書いて 2つのエンティティ間の 衝突に関する情報を提供します すでにロードされている AudioFileResourceを取得して その後 衝突した 最初のエンティティで再生します
よいスタートですが これでは どのタイプのオブジェクトが衝突しても 毎回同じ音が再生され その音量は衝突の強さにかかわらず 一定になります AudioFileGroupResourceを使用して 実装をさらに洗練させましょう AudioFileGroupResourcesは複数の オーディオファイルリソースで構成されます Entity.playAudioを AudioFileGroupResourceで 呼び出すたびに オーディオファイルリソースの中から ランダムに選択されて再生されます 衝突オーディオには 同じ音イベントの 微妙なバリエーションのセットを ロードできます
これにより オブジェクトが衝突するたびに 音が自然に変化します
宇宙船と小惑星は 非常にダイナミックであり 高速でも低速でも移動できます そのため 衝突したときの衝突音の大きさは 衝撃の強さを反映させる必要があります
蒸気跡のオーディオを フェードインさせたときのように Entity.playAudioから返される オーディオ再生コントローラを取得します 次に AudioPlaybackControllerの ゲインを設定し 両方のエンティティの速度から 計算されたレベルに設定します
これにより 2つのオブジェクトが 高速で正面衝突したときに 衝突音がパワフルになります
低速で衝突した場合は 衝突音が適切に減衰します
現在の実装では 衝突するすべてのオブジェクトに対して 同じセットの音を使用しています 宇宙船が小惑星やコンピュータの画面 または植物と衝突したときに 衝突する素材のペアに合わせた 音を出すことができます
まず アプリ内で発生すると想定される 一連の音を定義します 例えば 宇宙船はプラスチック製で 小惑星は岩でできています Studio環境の平面はすべて コンクリートや木 金属 ガラスなどの素材で ラベル付けされています
アプリ内では AudioMaterial列挙型と エンティティにAudioMaterialを保存する カスタムAudioMaterialComponentを 定義します 衝突音を発したい すべてのバーチャルオブジェクトに AudioMaterialComponentを設定します 小惑星には岩のAudioMaterialを 宇宙船にはプラスチックの AudioMaterialを設定します
2つのバーチャルオブジェクトが 衝突したときに まずそれらに設定された audioMaterialsを読み取ります 次に audioMaterialsのペアリングで インデックスされ すでにロードされた AudioFile GroupResourcesの セットから選択します これにより 宇宙船と小惑星の衝突音は プラスチックと岩の両方から 影響を受けます また 宇宙船とこのテーブルの衝突音は プラスチックと木から影響を受けます
現在の実装では バーチャルオブジェクトが 衝突するときに音を出すサポートが 追加されています Studio環境内の平面には すべて素材ラベルが付いているため 宇宙船がこれらの平面や物体に 衝突したときに カスタムの衝突音を提供する 能力が得られました しかし 仮想空間に限定する必要はありません これとまったく同じ動作を 現実世界の 平面や物体にも追加できます 現実世界の環境から再構築された ARKitシーンメッシュを使用して 部屋の異なる平面や 物体を識別するための メッシュ分類型を提供し 宇宙船がそれらに衝突したときに 音が再生されるようにすることができます この動作をどのように実装するか 見てみましょう
まず 動的オブジェクトが 衝突したメッシュの面を 特定する必要があります 次に この特定の面の メッシュ分類を読み取ります その後 メッシュ分類を カスタムAudioMaterial列挙型に マップします これで バーチャルおよび実物の オブジェクトの素材ペアに基づいて 正しい音を再生できます これらの動的オブジェクトが 現実世界の周囲と衝突したときに 何が起こるか聞いてみましょう 宇宙船が衝突する物体によって 衝突音が異なることに 注意してください 例えば 宇宙船がテーブルや iMacや椅子と衝突したときの音を 聞いてみましょう
いいですね 宇宙船を現実世界で飛ばすのは Studioのイマーシブ環境で飛ばすのと 同じくらい楽しいですね
仮想空間に入ると バーチャルオブジェクトが カスタムのイメージベースのライトで 異なる照明を受ける様子が見られます 同じことをオーディオにも 適用しましょう 仮想オーディオの音源が 現在私のいる部屋でなく この仮想環境に響いているように 聞こえるようにします 新しいReverbComponentと リバーブプリセットを使えば 新しい音響の世界に 連れて行ってくれます エンティティ階層内のどこかに ReverbComponentを 配置するだけです 一度に1つのリバーブが アクティブになります ワークフローに応じて Reality Composer Proで シーンにこのコンテンツを作成することも ここで私がしているように RealityKit APIを使用することもできます visionOS 1では RealityKitの すべての空間オーディオサウンドが 現実世界のリアルタイムシミュレーション 音響によってリバーブされます これは 視覚的パススルーを通じて 現実の周囲を見られる 混合型のイマーシブなユースケースに 適しています そうしたユースケースにおけるオーディオは 外観と同様 ユーザーのスペースに 存在するように聞こえる必要があります
visionOS 2でこれらの新しい リバーブプリセットを使用すると プログレッシブおよび フルイマーシブスペースで ユーザーを別世界に 連れて行くことができます プログレッシブイマーシブ環境では イマーシブレベルに応じて ユーザーの実際の音響が リバーブプリセットと混ざり合います フルイマーシブ環境では 空間オーディオの音源が ReverbComponentに設定された プリセットによってのみリバーブされます 今年のWWDCの Jonathanのセッション 「Enhance the immersion of media viewing in custom environments」 をチェックしてください Destination Videoサンプルで Reality Composer Proパッケージに リバーブを作成する方法を確認できます それでは 環境音楽再生で 雰囲気を設定する方法を見てみましょう
アプリの特定のフェーズに入ると その時々のムードにあった 音楽が再生されます
例えば Joy Rideフェーズでは 軽やかで浮遊感のある音楽が 空中に浮かんでいるように聞こえます しかしWorkフェーズに移ると 音楽はドライブ感を持って再生されます
この宇宙船の重要な特徴は 目の前だけでなく 周囲を飛び回れることです 新しい惑星が 背後に出現するかもしれないので 周囲の環境を見渡す必要があります 音楽は 宇宙船がどこに行っても 常にあるようにすると同時に 特定の方向からではなく 全方位から聞こえるようにします それによって アプリの広がりが しっかりと伝わるからです また 音源の各チャンネルが 仮想空間の固定された方向から 聞こえるようにして 音が頭の中から聞こえるように 感じさせないようにしたいと思います
ここでは クアドラフォニックと呼ばれる チャンネルレイアウトで 4チャンネルの音楽トラックを作成しました このチャンネルレイアウトでは 4つのチャンネルが周囲に 均等に配置されるため 映画のような映像向けに設計された 他のマルチチャンネル レイアウトに見られる 特定の前方方向が際立ちません また 音楽を作成する際には チャンネル全体に均等に オーディオ信号が分布するようにしました そのため どの方向を向いても バランスの取れたミックスが感じられます また エンジンのベーパートレイルや 排気音と同様 音楽トラックもシームレスに ループするようにし ポップ音やクリック音をなくしました RealityKitを使って この音楽トラックをアプリに どのように統合できるか見てみましょう
RealityKitにロードされる マルチチャンネルオーディオファイルには チャンネルレイアウトが 書き込まれている必要があります そうしないと RealityKitは オーディオファイルの各チャンネルを 正しい角度からレンダリングできません loadingStrategyは .preloadではなく.streamに設定します それがデフォルトです ストリーム読み込み方式では ディスクから オーディオデータをストリーミングし リアルタイムでデコードすることができます 一方 プリロード読み込み方式では オーディオデータを 読み込みプロセスの一部として 読み込みおよびデコードします ストリーム読み込み方式は メモリ使用量を減らす一方で 遅延が増加する場合があります 私たちの環境音楽には 例えば衝突音のような 厳密な遅延要件はありませんが 環境ファイルはかなり大きいので このユースケースには ストリーム読み込み戦略が最適です 次に 音楽再生エンティティに AmbientAudioComponent()を設定します 環境オーディオの音源は 3自由度でレンダリングされます 音源とリスナーの回転は考慮されますが 位置の変化は考慮されません アプリにはいくつかの異なる カテゴリのオーディオがあります ムードによっては 宇宙船からのダイナミックなオーディオと 衝突音と音楽を 同時に聞きたいこともあるでしょう しかし時には 音楽だけを聞きたいこともあります アプリのオーディオミキサーを使えば 各カテゴリのオーディオレベルを 個別に調整できます 飛行の感覚に浸りながら 完璧な雰囲気を作り出せます 実際に見てみましょう
まず 音楽の音量を下げます
次に 惑星の音を下げます
そして最後に 宇宙船の音を下げます
今度は 惑星の音を戻します
そして 音楽を加えて ミックスを完成させます
ではコードを見てみましょう まず 音楽の オーディオリソースを読み込みます AudioFileResourceの構成で mixGroupNameプロパティを 「Music」に設定します これは オーディオミキサーで調整する ミックスグループの名前になります これにより アプリ内のすべての 音楽リソースのレベルを操作できます 次に AudioMixGroupsComponentを 保持するエンティティを作成します ミックスグループのレベルが更新されたら AudioMixGroupを作成し そのゲインを設定します 最後に AudioMixGroupsComponentを構築し audioMixerEntityに設定します ここで行なったように UIの更新に合わせて AudioMixGroupsComponentを 更新できます AudioMixGroupsComponentは コンポーネントプロトコルに準拠しており カスタムRealityKitシステムの文脈でも 簡単に動的に更新することができます
素晴らしいですね オーディオミックスグループを使えば アプリ内の様々な音を制御し ムードに応じた体験を 生み出すことができます
今回は リアルタイム生成のオーディオによる 空間オーディオの音源を使って 宇宙船に息吹を吹き込み 仮想と現実のインターフェイスを 盛り上げる衝突音を作成してきました その後 これらの空間音響を リバーブプリセットで イマーシブな環境に組み入れました 最後に オーディオミックスグループを使って 音楽と音響の理想的なミックスを 作り出しました みなさんもぜひ アプリで遊んでみてください 皆さんがRealityKit Audioで 作成するものを楽しみにしています
-
-
3:11 - Play vapor trail audio
// Vapor trail audio import RealityKit func playVaporTrailAudio(from engine: Entity) async throws { let resource = try await AudioFileResource(named: "VaporTrail") engine.playAudio(resource) }
-
4:02 - Make vapor trail audio playback more dynamic
// Vapor trail audio import RealityKit func playVaporTrailAudio(from engine: Entity) async throws { let resource = try await AudioFileResource( named: "VaporTrail", configuration: AudioFileResource.Configuration( shouldLoop: true, shouldRandomizeStartTime: true ) ) let controller: AudioPlaybackController = engine.playAudio(resource) controller.gain = -.infinity controller.fade(to: .zero, duration: 1) let audioSource = Entity() audioSource.orientation = .init(angle: .pi, axis: [0, 1, 0]) audioSource.components.set( SpatialAudioComponent(directivity: .beam(focus: 0.25)) ) engine.addChild(audioSource) let controller = audioSource.playAudio(resource) }
-
7:10 - Exhaust audio
// Exhaust audio import RealityKit func updateAudio(for exhaust: Entity, throttle: Float) { let gain = decibels(amplitude: throttle) exhaust.components[SpatialAudioComponent.self]?.gain = Audio.Decibel(gain) } func decibels(amplitude: Float) -> Float { 20 * log10(amplitude) }
-
8:17 - Turbine audio
// Turbine audio import RealityKit var turbineController: AudioGeneratorController? func playTurbineAudio(from engine: Entity) { let audioUnit = try await AudioUnitTurbine.instantiate() let configuration = AudioGeneratorConfiguration(layoutTag: kAudioChannelLayoutTag_Mono) let format = AVAudioFormat( standardFormatWithSampleRate: Double(AudioGeneratorConfiguration.sampleRate), channelLayout: .init(layoutTag: configuration.layoutTag)! ) try audioUnit.outputBusses[0].setFormat(format) try audioUnit.allocateRenderResources() let renderBlock = audioUnit.internalRenderBlock turbineController = try engine.playAudio(configuration: configuration) { isSilence, timestamp, frameCount, outputData in var renderFlags = AudioUnitRenderActionFlags() return renderBlock(&renderFlags, timestamp, frameCount, 0, outputData, nil, nil) } }
-
11:28 - Setting distance attenuation and gain
import RealityKit func configureDistanceAttenuation(for spaceshipHifi: Entity) { spaceshipHifi.components.set( SpatialAudioComponent( gain: -18, distanceAttenuation: .rolloff(factor: 4) ) ) }
-
12:36 - Loudness variation
// Loudness variation import RealityKit func handleCollisionBegan(_ collision: CollisionEvents.Began) { let resource: AudioFileGroupResource // … let controller = collision.entityA.playAudio(resource) controller.gain = relativeLoudness(for: collision) }
-
14:44 - Defining audio materials
// Audio materials import RealityKit enum AudioMaterial { case none case plastic case rock case metal case drywall case wood case glass case concrete case fabric } struct AudioMaterialComponent: Component { var material: AudioMaterial }
-
14:53 - Setting audio materials
// Setting Audio Materials asteroid.components.set( AudioMaterialComponent(material: .rock) ) spaceship.components.set( AudioMaterialComponent(material: .plastic) )
-
15:04 - Handling collision audio
// Audio materials import RealityKit func handleCollisionBegan(_ collision: CollisionEvents.Began) { guard let audioMaterials = audioMaterials(for: collision), let resource: AudioFileGroupResource = collisionAudio[audioMaterials] else { return } let controller = collision.entityA.playAudio(resource) controller.gain = relativeLoudness(for: collision) }
-
17:18 - Reverb presets
// Reverb presets import Studio func prepareStudioEnvironment() async throws { let studio = try await Entity(named: "Studio", in: studioBundle) studio.components.set( ReverbComponent(reverb: .preset(.veryLargeRoom)) ) rootEntity.addChild(studio) }
-
20:05 - Immersive music
// Immersive music import RealityKit func playJoyRideMusic(from entity: Entity) async throws { let resource = try await AudioFileResource( named: “JoyRideMusic”, configuration: .init( loadingStrategy: .stream, shouldLoop: true ) ) entity.components.set(AmbientAudioComponent()) entity.playAudio(resource) }
-
21:57 - Using AudioMixGroup with a RealityKit entity
// Audio mix groups import RealityKit let resource = try await AudioFileResource( named: “JoyRideMusic”, configuration: .init( loadingStrategy: .stream, shouldLoop: true, mixGroupName: “Music” ) ) var audioMixerEntity = Entity() func updateMixGroup(named mixGroupName: String, to level: Audio.Decibel) { var mixGroup = AudioMixGroup(name: mixGroupName) mixGroup.gain = level let component = AudioMixGroupsComponent(mixGroups: [mixGroup]) audioMixerEntity.components.set(component) }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。