概要
Unity×C#の環境でマイクからオーディオを取得しWAVファイルとして保存するデモです。
開発環境
Windows 10
Unity 2019.4.31f1
Api Compatibility Level .NET Standard 2.0
実装
詳細はスクリプト中にコメントで記載しています。
DemoAudioRecorder.cs
using System.Collections;
using System.Linq;
using UnityEngine;
public class DemoAudioRecorder : MonoBehaviour
{
// Start is called before the first frame update
private string microphone;
private AudioClip microphoneInput;
private const int RECORD_LENGTH_SEC = 10;
private const int SAMPLE_RATE = 41100;
void Start()
{
// 利用可能なマイクを検出
microphone = Microphone.devices.FirstOrDefault();
Debug.Log("microphone: " + microphone);
if (microphone == null)
{
Debug.LogError("No microphone found");
return;
}
// 第二引数をtrueにすると循環バッファとしてループ保存
microphoneInput = Microphone.Start(microphone, false, RECORD_LENGTH_SEC, SAMPLE_RATE);
Debug.Log("録音を開始します。何か話してください。");
// Coroutine(非同期処理)でWaitAndExecuteメソッドを実行
StartCoroutine(WaitAndExecute());
}
// Update is called once per frame
void Update() { }
/// <summary>
/// 10秒間待機して、録音結果をWAVファイルに保存
/// Unity自体の処理を止めないようにコルーチンを利用して非同期処理にしています。
/// </summary>
IEnumerator WaitAndExecute()
{
// 10秒間待機
yield return new WaitForSeconds(10);
Debug.Log("録音を終了し、WAVファイルに保存します。");
// 保存先ファイルの設定
var filePath = string.Format("{0}/{1}/{2}", Application.persistentDataPath, "recordings", "recordedAudio.wav");
Debug.Log("filePath: " + filePath);
// AudioClipからWAVファイルを作成
SaveWavFile(filePath, microphoneInput);
}
/// <summary>
/// AudioClipからWAVファイルを作成
/// WavUtilityには以下のコードを利用。ただし、FromAudioClipメソッドの一部を修正
/// https://github.com/deadlyfingers/UnityWav/tree/master
/// </summary>
private void SaveWavFile(string filepath, AudioClip clip)
{
// AudioClipからWAVファイルを作成
byte[] wavBytes = WavUtility.FromAudioClip(clip, filepath, true);
}
}
WavUtility.cs(微修正したFromAudioClipメソッド部分のみ)
WAVファイルとして保存するスクリプトにはWavUtilityを一部書き換えて利用しました。
注意:以下のスクリプトは一部分のみです。これだけでは機能しません。
// すべてコメントアウト
// public static byte[] FromAudioClip(AudioClip audioClip)
// {
// string file;
// return FromAudioClip(audioClip, out file, false);
// }
// filepathがoutである必要はないので、outを削除
public static byte[] FromAudioClip(AudioClip audioClip, string filepath, bool saveAsFile = true, string dirname = "recordings")
{
MemoryStream stream = new MemoryStream();
const int headerSize = 44;
// get bit depth
UInt16 bitDepth = 16; //BitDepth (audioClip);
// NB: Only supports 16 bit
//Debug.AssertFormat (bitDepth == 16, "Only converting 16 bit is currently supported. The audio clip data is {0} bit.", bitDepth);
// total file size = 44 bytes for header format and audioClip.samples * factor due to float to Int16 / sbyte conversion
int fileSize = audioClip.samples * BlockSize_16Bit + headerSize; // BlockSize (bitDepth)
// chunk descriptor (riff)
WriteFileHeader(ref stream, fileSize);
// file header (fmt)
WriteFileFormat(ref stream, audioClip.channels, audioClip.frequency, bitDepth);
// data chunks (data)
WriteFileData(ref stream, audioClip, bitDepth);
byte[] bytes = stream.ToArray();
// Validate total bytes
Debug.AssertFormat(bytes.Length == fileSize, "Unexpected AudioClip to wav format byte count: {0} == {1}", bytes.Length, fileSize);
// Save file to persistant storage location
if (saveAsFile)
{
// filepathは引数として読み込むので、コメントアウト
// filepath = string.Format ("{0}/{1}/{2}.{3}", Application.persistentDataPath, dirname, DateTime.UtcNow.ToString ("yyMMdd-HHmmss-fff"), "wav");
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
File.WriteAllBytes(filepath, bytes);
//Debug.Log ("Auto-saved .wav file: " + filepath);
}
else
{
// コメントアウト
// filepath = null;
}
stream.Dispose();
return bytes;
}
利用方法
- Unityを起動します。
- Cube等のGameObjectを用意します。
- 用意したGameObjectにDemoAudioRecorder.csをアタッチします。
- Console画面を開き、Playモードに入ります。
- Consoleに表示される指示に従って、マイクに話しかけます。
- 録音が完了したら、filePathに表示されるフォルダを開き、recordedAudio.wavを確認します。
- きちんと録音できていたら、成功です。
参考資料