[UI] オーディオ信号の周波数グラフを作成しよう！オーディオBPからUIに映るまでの構造

## はじめに
こんにちは、初投稿です！
僕がUIのマテリアルを研究し続けていて丁度「オーディオ信号の周波数グラフ」を作成してみたかったところです。いい機会なので記事にまとめてUEアドベントカレンダーに載せようと思ったきっかけです。
こちらの記事ではラジアルとリニア形式、グラフの２パターンをご紹介していきます。
初心者も作れるように画像とステップを多く含めました。ベテランならばどんどん飛ばして確認したい項目のみでもご確認いただければと思います。


グラフはこちらのものです。
<img width="350" alt="UnrealEditor_aRyAAjvD5D.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/a634bb9b-0891-f376-c747-9d0d7fdbf3ef.gif">   <img width="350" alt="UnrealEditor_MSmTsODLgq.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/8db10a37-bb88-2ac8-59c7-f98f655e6f29.gif">


### 音に関する豆知識
本番に入る前に、作り方に当たって最低限こちらのオディオ知識が必要となります。よーく見かけるものに関わらず、意外とグラフの読み方知らない方が多いのではないかと思います。（恥ずかしながら僕はそうでした）
分かりやすく説明するためこちらのシンプル図を用意しました。
X方向には可聴周波数（Hz)幅でY方向には音圧(dB)です。横方向は左が低い音を示し、右が高い音です。縦方向は音の圧力、量のことですね。バーが高いとうるさいということです。
という訳で、このパラメーターがあればグラフが作れます。

<img width="450" alt="Flowchart (2).jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/3802c24c-8f22-069a-59fb-2408ac4ef9ac.jpeg">


### 作りこなせばできるようになること
最後まで作ってしまえばこちらの要素ができるようになります。

ー　RenderTargetへ描画する方法
ー　BPからマテリアルに値を渡す方法
ー　Synesthesia NRTというサウンドプラグインの設定方法
ー　BPインターフェスの使用方法





## 準備
環境と必要なものまとめです。

ー　UE5
ー　Audio Synesthesia (プラグイン）
ー　サウンド（.wav)を用意　（最低限１ｘ）

Audio Synesthesiaはサウンドファイルの情報を読み取りBPで扱うようにしてくれる、便利なプラグインです。

デフォルトにUE5にインストールされているはずですが、念のためご確認しておいてください。
Beta版になってます。プラグインメニューからチェックが入っていれば大丈夫です。
![Screenshot_76.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/dffe1fbf-9a71-81a1-5bd3-109da2a04006.png)



## 目次
ー　フローのご紹介
ー　① NRT作成とSoundの設定
ー　② BPInterfaceの作成
ー　③ WidgetとRenderTargetの作成
ー　④ ActorBPの作成
ー　⑤ MaterialVisualの作成　（バーの作成）
ー　⑥ MaterialRenderの作成
ー　テスト
ー　NRTSetting説明

## フローのご紹介
詳細に入る前に迷わずアセットがどのように繋いでいるかをご理解していただくためにこちらの大まかなフロー図を用意しました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/38532f14-67dc-6b89-2ae3-0e905e79f090.png)


名称|解説
---|---
NRT|サウンド情報を収穫してくれるアセット（プラグイン）
Sound|サウンドファイル
Actor BP|ウイジェットとサウンド間に値渡しするBP
Widget HUD|画面に映るWidget
BP Interface|BP間に値渡しをシンプル化してくれるもの
Widget Render Target|RenderTarget描画管理するウイジェット
Material Visual|バー作成するマテリアル
RenderTarget Texture|バーが描かれるテクスチャー
Material Render|MaterialVisualの透明度をサポートしてくれるマテリアル


### 描画処理説明と最適化について
毎フレームにRenderTargetへバーを書き込み、バーの数により描画回数が決まります。つまり、バーが多ければ多いほど描画回数が増して処理が重たくなります。具体的の例を挙げるとバーを40描画するには1フレーム当たり40回バーのポジションと長さを計算しRenderTargetへ出力します。。ここのRenderTargetは保存テクスチャーとして使用され、バーが全部揃った時点でMaterialRenderを通してアルファを反対し、１フレーム当たりの描画結果をスクリーンに写します。

処理が多いため、こちらの制作フローが最適化されておりません。本来はマテリアル内で解決したかったのですが、BPからの配列変数をマテリアルに渡せない代わりにRenderTargetテクスチャーをしました。
プロファイリングはまだしておりませんが、興味深いです。いつかの課題として残しておきます (笑

こちらの図は上記に解説したRenderTargetの使い方です。マテリアルを何回も通してRenderTargetに描画して、処理が終わると描画結果を出します。それを毎フレームに行います(!!)
![byougamaisuu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/407b0152-1102-28bd-f6bc-61f9fcb9fb7f.png)



## ① NRT作成とSoundの設定
さて、本編に入りましょう。
まず.wavのファイルをUEに入れます。このようなアセットが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/d25de504-89e7-96e5-e4b3-1d672d5ab72f.png)
僕は無料BGM、[Musmus](https://musmus.main.jp/music.html)というサイトからサウンドをダウンロードしました。
.wavがなければオンラインで簡単にどんな拡張子からでも.wavに変換できるコンバーターが存在します。


次に、オーディオ情報管理ができるNRTファイルの作成です。サイドメニュー（右クリック）からAudio>Analysis>SynesthesiaNRTを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/b210ace8-4ecd-c0c1-ba4f-dec3fa39eb0f.png)

ウインドウが現れます。**ConstantQNRT**と**LoudnessNRT**一つずつ作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/bab38d62-38f3-c91c-95f3-447d2a335e14.png)


:::note info
ConstantQNRTは周波数情報に該当するものです。ConstantQNRTだけでグラフが成り立てます。値は配列形式で出力されます。バーの位置は配列のIndexで定められ各Indexにある値が音圧に該当します。
:::
:::note info
LoudnessNRTは音圧に該当するものです。こちらの音圧は全周波数合計に該当し、ラジアルマテリアル中心の円がリズムについてくるようにLoundnessNRTを使用します。
:::

次に、Audio>Analysis>Synesthesia NRT Settingを作成します。
周波数を調整したいだけなので作成するのは**ConstantQNRTSetting**だけで十分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/e3a59431-1eb7-7e03-17f6-6512b022bd7b.png)



合わせてアセット３つになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/bd0ef832-4c4c-778b-9e1e-411926da7bb2.png)
各アセットの設定をしましょう。

### ConstantQNRT
先ほど作成した**ConstantQNRTSetting**とサウンドをこのように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/938b11e4-17b0-d7db-5e21-169d6f7d59a5.png)

### LoudnessNRT
今回はLoudnessNRTSettingsを作成していないので**DefaultLoudnessNRTSettings**のままで大丈夫です。サウンドは上記と同様です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/fb4394e0-02bd-5cb7-9e72-a4013634338c.png)

### ConstantQNRTSetting
ここはグラフのパラメーターを調整できる場所です。とりあえずこのように設定しておけばよいでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/4b320e71-3aa8-de0e-251b-dba4f7b6ed0d.png)


:::note info
重そうと思えばFFTSizeをLargeもしくはXLargeにするとよいです。
:::
SartingFrequencyは最小数の周波数を示すものです。値が高いとバーが減りますので、常に最小値(20)にしておきます。

:::note warn
NumBandsはバーの数になります。バーが多いと描画の回数が増え処理が重いのでご注意を。
:::
Noise(dB)は最終的にバー合計の高さを調整できるのでその段階で弄りません。
それ以外はほぼ触っていないです。パラメーターに関してご興味があればこちらの公式ページをご確認ください。

https://docs.unrealengine.com/5.0/ja/audio-synesthesia-in-unreal-engine/#%E3%83%8E%E3%83%B3%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0_nrt_%E8%A7%A3%E6%9E%90

これでサウンド編が完了です。


## ② BPInterfaceの作成
こちらのアセットの役名はクラスの親子を気にしないで変数をWidgetとBP間に簡単に渡せる、非常に便利なものです。BPとBPのつなぎ込み方法は色々あるのですが、今回はBPInterfaceがどのものなのかを含めて見たかったので使用しました。
サイドメニューのBlueprint＞BlueprintInterfaceを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/3a1aa51b-8862-241e-e7ee-3ab78f4b2fb7.png)

開いてから空なのでファンクション１つ追加します。「Add」ボタンを押し「OnSetSynthetiseur」という名をつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/d61ba30f-ea38-51a8-985d-584619af8200.png)

InputセクションにはこのようにFloat変数４つ作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/e80b214b-8b16-0373-d446-9bdbe24d5252.png)

名称|解説
---|---
Db|一定時の音圧（バー１本当たりの高さ）
FreqNb|可聴周波数の幅　（バーの数）
FreqHz|一定時の周波数（バー１本当たりの位置）
Loudness|音圧合計（円型マテリアルの中心に使用）

保存し、閉じましょう。BPInterfaceを完成しました。

## ③ WidgetとRenderTargetの作成
ウイジェットはWBP_HUDとWBP_RenderTarget、２つ作成します。

サイドメニューからUserInterface>WidgetBlueprintから作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/88643861-7789-bcb7-9a47-81995df4db0d.png)

両方UserWidgetクラスにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/93ed5c4a-21f1-9a1a-b23d-95f90158228e.png)



### WBP_RenderTarget
こちらはImage一枚が十分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/89dcd1cf-b8f6-b81b-223f-99d3cd61f1cc.png)

#### 変数とBPInterfaceの設定
BPInterfaceがWidgetから見えるため、ClassSettingsよりBPInterfaceを繋げておきます。Addボタンを押して作成したBPInterfaceをリストから選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/51fd797e-99d1-0f6b-9395-a22405e6cdf0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/2b182b84-7516-70ce-331b-0f13dbe9862e.png)


次に必要な変数を作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/fd0e4073-594f-4b59-1c3a-c8f325ab5d91.png)
TextureRenderTargetを設定するにはRenderTargetというテクスチャーが要るのでまず作りましょう。

#### RenderTargetテクスチャーの作成方法
サイドメニューからTexture>RenderTargetを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/aeeb03ae-0ff4-6b13-38ef-c08265633703.png)

テクスチャーセッティングはこのようにしておきました。２Kが大きいですが、研究プロジェクトなのでとりあえずよいクオリティで出しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/6a9f2288-024e-9c69-5837-aaecaefbee57.png)

できたテクスチャーをWBP_RenderTarget内のTextureRenderTarget変数に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/45b6488e-e630-8c3f-5177-c7b24013c6c2.png)

RenderMaterial内にはステップ⑤番に作る予定のマテリアルを入れますが、一旦変数だけ作っておいて後に戻って繋げましょう。
DynamicMaterial変数はBPで定義します。（次のステップ）


#### Graph
CustomEventはこのように作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/19de7c6f-7279-30dc-102e-5a510b3419c6.png)

OnSetSynthetiseurは先ほど接続したBPInterfaceから呼び出せます。右クリックしOnSetSynthetiseurを検索すれば出てくるはずです。
このようにノードを繋げます。MaterialParameterの名称に気をつけましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/223aeea1-d05d-a44a-2244-ea5b7d15caf5.png)



### WBP_HUD

ウイジェット内は黒背景とContainerを作成しています。Containerはなんでもいいです。Canvas,OverlayもしくはGridPanel。ウイジェットGraphからWBP_RenderTargetを生成してContainerの子供として加えますので、UMGのヒエラルキーに直に置きません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/6e56de4f-bb62-49c1-13e8-3b2ed1bd7585.png)

ウイジェットのGraph（BP）側ではOnInitRenderTargetのCustomEventを作成し、WBP_RenderTargetを生成した後に変数化しContainerに追加します。ReturnValue上に右クリックして「Promote to Variable」で変数化してくれます。Createノードは「Create Widget」の検索から生成できます。Class中には先ほど作ったWBP_RenderTargetウイジェットを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/ec2c04fd-ab80-6d12-7a73-bb4e4edfea29.png)

そのOnInitRenderTargetはのちほどActorBPから呼びます。次のステップ（ActorBP）に移りましょう。






## ④ ActorBPの作成
Actorブループリントを作成します。サイドメニューからBlueprint>BlueprintClassを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/e82acd59-bca5-6983-37ea-fa0101752f9e.png)

クラスはActorです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/0d54359c-315e-992c-35eb-1df209aa0afe.png)


そのブループリント中にはオディオコンポネントを追加し、変数はLoudnessNRT、ConstantNRT、CQ（Float配列）とWBPHUD（HUDのウイジェットクラス）を作成します。
<img width="300" alt="Screenshot_85.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/66c39387-b4e5-e56d-0e71-683c5e686bf3.png">

コンポネントオーディオを選択しながらDetailsタブ内にサウンドアセットを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/2919ef5d-5438-b46b-1bae-fe578c3da4c5.png)




#### Graph
BeginPlayノードからサウンド設定、CreateWidgetからWBP_HUDを生成し、Viewportに出します。ゲーム開始時にサウンドが再生するようにPlayノードも入れておいてCQ変数の初定義をします。(CQ変数は毎フレームに更新する必要があるのでBeginPlayに必要ないかもです、念のため定義しておきました)
![Screenshot_74.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/2761554d-e03d-6a4c-ed8a-d1b016fdd9d5.png)


OnSynthetiseur（Call Message）ノードを出してTargetにはHUDの子供であるWBP_RenderTargetを接続します。それでUEがWBP_RenderTargetウイジェットへオーディオ情報を送り、RenderTargetのテクスチャーに描画するようにできました。
ループに入る前に、CQ変数を更新し、各パラメーターに情報を渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/1bf60a1b-1e6f-9f2a-a9ae-2c4890967440.png)

次はいよいよマテリアル編に入ります。

## ⑤ MaterialVisualの作成　（バーの作成）
マテリアルはサイドメニューから直接にマテリアルを選択すると作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/713c7c64-cae5-84cb-a286-6ea51478bbe7.png)

マテリアルをUserInterfaceとTranslucentにします。マテリアル内のDetailsパネルから変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/058a9d18-96b8-1dbd-af30-bb39777cebe7.png)




さてと、下記のグラフに移ります。
分かりやすくするため、マテリアルファンクションを作成しました。(MF_SynthBar)
下記スクショに詳しくノードを載せています。



オーディオ用のパラメーターは先ほど設定したActorBPでの値はオーディオアセットからの情報をウイジェットに送り出されてマテリアル内の値は上書きされますので、ここでは仮な状態でよいです。

IsCircularノードは「Switch Parameter」です。On/Offにより縦型、ラジアル型で姿を入れ替えられます。


![Screenshot_79.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/92ef9f3f-9ede-339c-766e-c175ec42e682.png)

:::note info
GradientScale,GradientOffsetXとGradientOffsetYはラジアル型限定のパラメーターです。
バーの長さによりColor2が見えなかったりするのでグラデーションの見るどころを調整するためのパラメーターです。
:::

### MF_SyntBarの詳細
マテリアルファンクションの詳細に入ります。グラフが少し大きいので部分を取り分けてスクショを載せます。
バーの姿２つあるのでOutputノードを２つ用意してます。
![Screenshot_80.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/929b4ca2-539d-2f4f-5ca3-0b4dbccbc8be.png)

まず、マテリアルファンクションの作成方法。
サイドメニューからMaterial>MaterialFunctionを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/30faf02d-d2d5-06b1-462d-ae2c489b3208.png)
できたファンクションアセットをマテリアルにドラッグ・アンド・ドロップすればノードとして出現します。

ファンクションの中身ですが、名称付けられるRerouteを使用し、ぐちゃぐちゃならないようINPUTをこのようにまとめます。
![Screenshot_81.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/159ca8ae-43a0-9709-e707-4d935f7f9eb6.png)

### Linear
バーの縦型、リニア編です。
![Screenshot_82.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/ef417482-a797-1180-8f51-a853ab907022.png)

### Radial
RadialUVは別の名称付のRerouteを作成しこのようにUVを極座標系に変換します。
![Screenshot_83.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/797c4263-7b10-c2ba-1702-4ee89b5ac2fe.png)


![Screenshot_84.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/6527e887-3d14-0a2b-b11d-dfce84381def.png)

色々ノードを繋げていますが、一つ一つ説明していくとより長くなってしまうので今回は省略してスクショを参考にして再現していただければと思います。

### マテリアルインスタンスを作成
マテリアルができると、インスタンスを作成します。マテリアルを右クリックし、Create Material　Instanceを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/5ede84ad-be51-d83b-6dda-c2cb81bfaf6d.png)

そこからパラメーターをいじって確認できます。楽しい！
![UnrealEditor_yK9ifeEkIq.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/4b6b9d12-147e-57f9-52b7-f82d51fe4a5d.gif)

isCircularにチェックを入れるとラジアル形式で、はずすと縦バーの形式に代わることが確認できます。
![UnrealEditor_sKu4KnmLwF.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/01f9b85a-73d8-230b-82c7-80579ace4786.gif)


:::note info
バーは一本しか見えないのは正しいです。全バーが表示されるのはRenderTargetだけなのでBP処理が入らないと見えないです。
:::
ラジアル型とリニア型一つずつのインスタンスを作ってしまうといいかもしれません。BPでインスタンスを差し替えればよいし、インスタンス内のIsCircularを調整すれば同じ結果にできます。ただし、SwitchParameterはランタイムで制御できないので注意しましょう。

### 忘れずにWBP_RenderTargetにマテリアルを設定しましょう
WBP_RenderTarget再び開き、RenderMaterialに作ったマテリアルインスタンスを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/bee1f906-50be-664b-17a5-24963683c7e0.png)


## ⑥ MaterialRenderの作成
先ほど作ったマテリアルをそのままRenderTargetに描画してもよいのですが、透明度に問題があるため、透明度が美しく映るように別マテリアルを作成してます。どういう問題なのかは気になる方は[こちらご確認ください。](https://forums.unrealengine.com/t/draw-material-to-render-target-node-has-inverted-alpha/366244)

新たなマテリアルを作成し、ドメインをUserInterface、ブレンドモードをAlphaCompositeにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/c1b200cc-1884-7e9e-733e-231690794723.png)

ノードはシンプルです、作ったRenderTargetのテクスチャーをSamplerに設定し、変数化します。そしてSamplerのアルファをリバースするだけです。
![Screenshot_78.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/d87cc8aa-cce9-51d5-f14b-71d3991a6371.png)

### WidgetにMaterialRenderを設定
最後に作ったWBP_RenderTargetがマテリアルを映すためにImageにマテリアルを割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/10699eba-2083-dcad-c0f7-7a90fa6f27c6.png)


これですべての設定が完了しました。


## テスト
テストはActorBPを好きなシーンにおいて再生するだけです。WBP_HUD黒背景なしでも３Dシーン上に表示できますよ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582194/4a20d6da-4d76-e6ae-b75f-d95aa93ca14c.png)

:::note warn
**懸念点**
背景が黒くないとバーのエッジに白いピックセルが少し写ってしまいます。原因はまだ調べ中です。
また、ラジアル型では最初と最後のバーがどうしてもくっついているのですが、マテリアルを少し調整すればきれいに並べられる気がします。
:::




## NRTSettingについて
最初に作ったNRTSettingを再び開き、バーの数、周波数の幅を調整できます。

:::note warn
バグかもしれませんが、NRTSettingを保存するだけでパラメーターが更新されないようなのでご注意ください。煩わしいですが、ConstantQRTアセットに変更がないとセッティングが渡り移らないようです。僕は毎度ConstantQRTのサウンドを変えて戻してあげて保存するようにしてやっとNRTSettingの最新パラメーターが適用されます。
:::
## 最後に

思ったより長い記事になりまた。お疲れ様です！
コメントや開発アドバイス、記事の書き方アドバイス、ご質問などがありましたらいつでもTwitter（X）上でご連絡ください。
https://twitter.com/ko_yuki_lo