【Unity】AudioListerを録音してwavにする
録音する
Unity内で鳴っている音をそのまま録音します.
ソースコードはこちら.
using System; using System.IO; using System.Text; using UnityEngine; [RequireComponent(typeof(AudioListener))] public class AudioListener2Wav : MonoBehaviour { private int m_outputRate = 44100; private bool m_isRecording = false; private FileStream m_stream; readonly private string m_fileName = "recTest.wav"; readonly private int m_headerSize = 44; float[] wave = new float[1024]; void Update () { if (!Input.GetKeyDown(KeyCode.R)) return; if (m_isRecording == false) { Debug.Log("rec started",this); m_isRecording = true; startWriting(m_fileName); } else { m_isRecording = false; writeHeader(); Debug.Log("rec stop", this); } } private void OnAudioFilterRead(float[] data, int channels) { if (!m_isRecording) return; convertAndWrite(data); } /// <summary> /// ストリームを0埋めして初期化 /// </summary> /// <param name="name">ファイルの名前</param> private void startWriting(string name) { m_stream = new FileStream(name, FileMode.Create); var emptyByte = new byte(); for (int i = 0; i < m_headerSize; i++) { m_stream.WriteByte(emptyByte); } } /// <summary> /// 変換してストリームに書き込む /// </summary> /// <param name="dataSource">書き込むデータ</param> private void convertAndWrite(float[] dataSource) { Int16[] intData = new Int16[dataSource.Length]; var bytesData = new byte[dataSource.Length*2]; int rescaleFactor = 32767; for (int i = 0; i < dataSource.Length; i++) { intData[i] = (short) (dataSource[i] * rescaleFactor); var byteArr = new byte[2]; byteArr = BitConverter.GetBytes(intData[i]); byteArr.CopyTo(bytesData, i * 2); } m_stream.Write(bytesData, 0, bytesData.Length); } /// <summary> /// ヘッダを書く /// 詳しくはwavのフォーマットを確認 /// http://www.graffiti.jp/pc/p030506a.htm /// </summary> private void writeHeader() { m_stream.Seek(0, SeekOrigin.Begin); Byte[] riff = Encoding.UTF8.GetBytes("RIFF"); m_stream.Write(riff, 0, 4); Byte[] chunkSize = BitConverter.GetBytes(m_stream.Length - 8); m_stream.Write(chunkSize, 0, 4); Byte[] wave = Encoding.UTF8.GetBytes("WAVE"); m_stream.Write(wave, 0, 4); Byte[] fmt = Encoding.UTF8.GetBytes("fmt "); m_stream.Write(fmt, 0, 4); Byte[] subChunk1 = BitConverter.GetBytes(16); m_stream.Write(subChunk1, 0, 4); UInt16 one = 1; UInt16 two = 2; Byte[] audioFormat = BitConverter.GetBytes(one); m_stream.Write(audioFormat, 0, 2); Byte[] numChannels = BitConverter.GetBytes(two); m_stream.Write(numChannels, 0, 2); Byte[] sampleRate = BitConverter.GetBytes(m_outputRate); m_stream.Write(sampleRate, 0, 4); Byte[] byteRate = BitConverter.GetBytes(m_outputRate * 4); // sampleRate * bytesPerSample*number of channels, here 44100*2*2 m_stream.Write(byteRate, 0, 4); UInt16 four = 4; Byte[] blockAlign = BitConverter.GetBytes(four); m_stream.Write(blockAlign, 0, 2); UInt16 sixteen = 16; Byte[] bitPerSample = BitConverter.GetBytes(sixteen); m_stream.Write(bitPerSample, 0, 2); Byte[] dataString = Encoding.UTF8.GetBytes("data"); m_stream.Write(dataString, 0, 4); Byte[] subChunk2 = BitConverter.GetBytes(m_stream.Length - m_headerSize); m_stream.Write(subChunk2, 0, 4); m_stream.Close(); } }
同じGameObjectにAudioListenerがいないと
OnAudioFilterReadがコールされません.(ハマりました)
使い方
- AudioListerのついたGameObjectにアタッチ
- Rボタンを叩く(録画開始)
- 再度Rボタンを叩く(録画終了)
参考
参考にした元のソースはこちらにあります.
ただしこちらはUnityScriptです.
https://forum.unity3d.com/threads/writing-audiolistener-getoutputdata-to-wav-problem.119295/