Unityやってみる24:【AudioSource】サイレンっぽい音を、うーうー鳴らしてみる
こんにちは。Unity素人おじさんです。ただしプログラミング歴は結構長いです。
「スクリプトだけで何かする」チャレンジをひとまず中断し、オーディオ関係の機能をいじってみることにしました。
で、ChatGPTにスクリプトを書いてもらったり、音源を自作したりして、「サイレンをうーうー鳴らすデモ。スペースキーで音のオンオフ、キーボードの左右で音程の変更」、を実現できました。
スクリプトはすべてChatGPTに任せたため、ほぼほぼ何も理解できてないのですが、コンポーネント指向プログラミングでは、理解するよりも出来ることを増やしていくことが重要です。ありがたく利用させていただきましょう。ありがとうChatGPTくん(笑。
では簡単に手順を説明していきます。
方針としては、「音の鳴らし方が確認できればいい。余計なオブジェクトはいらない。極力シンプルに簡単に」、とします。
まずいつものように、プロジェクトを新規作成します。テンプレートは「3D コア」を使います。作成後Unityエディターで開くと、こうなりますね。カメラとライト以外は、何もない状態です。
今回は、音だけ鳴らせればいいので、上記にいきなりオーディオソース・オブジェクトを配置しちゃいます。その手順は次の通りです。
①別途用意した音源(wavファイル)を、上部メニューの「Assets」→「Import New Asset」で、インポートする。
私が実験用に用意した音源はこれ。実験したい人はダウンロードしてお使いください。
※効果音用の音源は、mp3でなくwavで用意した方がいいです。理由は後述。
②インポートした音源アセットのアイコンを、ヒエラルキーパネルにドラッグ&ドロップしてシーンにセットする
配置された音源アセットには、AudioSouceコンポーネントが自動でアタッチされます。それにより、スクリプトから、AudioSouceとして利用可能となりますね。
なお今回、サイレンのような連続音を鳴らそうとしているので、AudioSourceの設定の「Loop」にチェックしておきましょう。忘れやすいので注意です。
追記:Loopのチェックを忘れた時のために、スクリプトでチェックを自動でで付けてもいいですね。
③セットしたAudioSourceに、「Add Component」→「New Script」で新規スクリプトをアタッチする。名前は「AudioController」としておく
④アタッチしたスクリプトをエディターで開いて、サウンド制御用のスクリプトをコピペして保存する
コピペするスクリプトはこれです。コメントも含め、すべてChatGPTが書いてくれたものです。理解は後にして、ひとまず何も考えずにコピペしましょう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioController : MonoBehaviour
{
public AudioSource audioSource; // オーディオソース
public float pitchChangeSpeed = 1.0f; // 音程の変化スピード
private bool isPlaying = false; // オーディオ再生中かどうか
private float targetPitch = 1.0f; // 目標の音程
void Update()
{
// 左キーで音程を下げる
if (Input.GetKey(KeyCode.LeftArrow))
{
targetPitch -= pitchChangeSpeed * Time.deltaTime;
}
// 右キーで音程を上げる
if (Input.GetKey(KeyCode.RightArrow))
{
targetPitch += pitchChangeSpeed * Time.deltaTime;
}
// スペースキーでオーディオの再生をオン/オフする
if (Input.GetKeyDown(KeyCode.Space))
{
if (isPlaying)
{
audioSource.Stop();
isPlaying = false;
}
else
{
audioSource.Play();
isPlaying = true;
}
}
// 音程を0.1~2.0の範囲にクランプする
targetPitch = Mathf.Clamp(targetPitch, 0.1f, 2.0f);
// オーディオの音程を目標の音程に近づける
audioSource.pitch = Mathf.Lerp(audioSource.pitch, targetPitch, Time.deltaTime);
}
}
⑤インスペクターパネルから、AudioSourceの設定が可能になるので、シーンにセットしたAudioSource自体を、ドラッグ&ドロップする
⑥実行して確認する
以上で実行の準備は完了です。実行してみました。ゲームビューには何も表示されていませんが、キーボードの左右で音の高さ変更、スペースキーでオンオフが、実現されています。またインスペクターパネルの、AudioSourceコンポーネントの、pitchという設定が、キーボードの左右で変化します。音の高さは、Pitchを変更することで、変えられるんですね。
あまり高い音にすると、耳が痛くなります💦
追記:うまく左右のキーを操作すると、ぐずる赤ちゃんの声みたいになります。めっちゃうるさいです(笑。
音の高さを上げる場合は、同時に音量を下げるようにした方が、いいかも知れません。また無理やり高周波や大音量を出し続けると、PCにダメージを与える可能性が高いので、注意が必要です。今回のスクリプトでは、Mathf.Clampという関数で、音程(Pitch)を0.1f~2.0fの範囲に制限してくれているようです。
以上が、音を出して音程を調整する方法でした。ここからは、サイレン用の音源(wav)をどうやって作ったかを、比較的詳しくご説明しておきます。
今回、とあるYoutubeの動画の、津波警報の音を使わせていただきました。作りたいのは時間の経過によらず、音程・音量が一定の「単調音」であるため、電子的な音とか、機械的な回転音であれば、なんでもいいはずです。ただ、うまく切り取らないと、おかしな音になってしまうかも知れません。
私が録音とか加工に使っている、「Audacity」というフリーソフトの画面で、簡単にご説明します。
下の図は、警告音全体を録音してみた波形です。横軸が時間です。縦軸は音の強弱です。
最初は低い音から始まって、音量や音程が、上がったり下がったりしながらだんだん一定の音程になり、しばらくそのままなり続けます。1.5秒当たりから右は、ほぼほぼ一定の波形になり、それが3.0秒くらいまで続いていますね。今回のデモのような、音量も音程も一定な、「単調音」が必要な場合、安定している右の方を狙って切り取って、wavに保存するといいですね。
一つ注意点です。音の大きさというのは、音の強さで表現できますから、上の波形の上下への振れ幅の大きさで、確認することが出来ます。
しかし音の高さというのは、音が上下する速さ、つまり「周波数」によって決まりますから、上の波形ではそれがつぶれてしまっていて、確認できませんね。ご参考までに0.5秒辺りの波形と、2.5秒辺りの波形を、拡大してみましょう。
まず0.5秒の付近の拡大波形です。波形があるパターンを形成しているのが見えますね。そのパターンの10個分を、選択した状態です。赤で囲った部分に、その選択した始点と、終点の時刻が表示されています。0.490秒から0.511秒、つまりこの波形の周期は、(0.511-0.490)/10で、0.0021秒となります。周波数f=1/t=1/0.0021=476なので、周波数は476Hzということになります。
次に、2.5秒辺りの拡大波形を見てみましょう。だいぶ波形の幅が短くなっていますね。音程が上がっているということです。波形の周期はt=(2.553-2.540)/10=0.0013秒、周波数を計算すると、f=1/0.0013=769Hz、となります。
最初は大体476Hzだったのが、最後は769Hzで安定。769/476=1.616倍。
ここで次の表を見てください。ChatGPTが、私の要望に従って作ってくれたものです。ドレミの「ド」の周波数を1とした場合に、次のドまでのそれぞれの音の、周波数がその何倍になるかを示したものです。1.616倍というのは、だいたいラの位置に近いですね。つまり私がサンプルに利用させていただいたサイレン音は、ドレミで表すと、「ド~~~ォオオラァアアア!」って表現できるようです(笑。
ちょっと脱線しましたけど、録音した音源の、安定した部分を切り出すための、考え方でした。
さらにいくつか、注意点です。
①切り出す波形は、左右がつながってないといけない。
次の図は、悪いサンプルです。選択範囲(水色部分)の左と右で、波形の高さが一致していないです。これだと連続再生した時に、ブツブツとノイズが乗ってしまいます。
次の図が、正しいサンプルです。波形が中央の線と重なる部分から始まり、重なる部分で終わっています。このように切り取れていると、ループ時のブツブツというノイズを、減らすことができます。
②切り取る波形の長さは、ある程度長くしておく
上の2枚の画像では、波形を1つ~2つ分で切り取っていますけど、あまりに短い時間でLOOP処理させた場合、AudioSourceコンポーネントの、STOPイベントの検出処理と、音源の再生処理だけで、PCがすごい負担を強いられることになりそうです。
そうすると何が起こるかというと、普段は起こらない処理を超高速に強いられることになったPCが、発熱したり、激しく劣化したりすることになります。一定の単調な音の再生だけでいいので、そんなに高速にループさせる必要は、全くありませんね。なのである程度以上の長さに、しておきましょう。
何秒くらいが適切かは、実行しようとしているハードなどで違うと思いますが、「0.5秒以上は欲しい。1.0秒以上あれば安心」、くらいの目安を持っておけば、いい気がします。Unity素人おじさんである、私が言ってることなので、あまり信用しないようお願いします(笑。
③切り取った波形を保存する際の形式は、mp3はダメ。wavにしておく
なぜmp3だとダメかというと、そもそもmp3は、楽曲を効率よく保存するためのものなので、次のように勝手に空白の時間を入れられちゃうんですよね。私は今日知りました(笑。
以上、今日はUnityで、サイレンをうーうー鳴らしてみました(笑。
AudioSourceコンポーネントには、他にもいろんな設定がありますね。
1日2日で理解できるものではなさそうですが、今後も勉強して、何かわかったらご報告してきます。
この記事が気に入ったらサポートをしてみませんか?