ã¯ããã«
ä»å¹´ã¯ããã« Unity ã® WebGL ãã«ãã§ãã¤ã¯å ¥åã使ããããã«ããã©ã¤ãã©ãªãä½ãã¾ããã
ãã ã次ã®è¨äºã«ãè¨è¼ããã®ã§ãããã©ãããé²é³æã«é³å£°ãé ããªã£ã¦ãã¾ãï¼ããããä½ããªã£ã¦ãã¾ãï¼ã¨ããåé¡ãããããã§ãã
æ¬è¨äºã§ã¯ããã¡ãã®èª¿æ»ã¨ä¿®æ£ãè¡ã£ãçµæãã¾ã¨ãããã¨æãã¾ãã
ãªãªã¼ã¹
åé¡ã¨å¯¾å¿
ããããä½ããªãã®ã¯ãããããã«ããã£ã³ãã«å ¥åã®ãããã¡ãã¢ãã©ã«ã® AudioClip ã®ãããã¡ã«å ¥ãã¦ããããããªãã¨å½ãããã¤ãã¾ãããã©ã¤ãã©ãªå ã«ã¯ 2 ç®æãã¢ãã©ã«ãåæã¨ããå¦çãè¡ã£ã¦ãã¾ã£ã¦ããå ´æãããã¾ãã
AudioClip ã®çæ
ã¾ãã¯é²é³çµäºæã§ããAudioClip.Create()
ã§ã® AudioClip çææã«ã¯ãå¼æ°ã«ãã£ã³ãã«æ°ãæå®ããå ´æãããã¾ããç¾ç¶ã¯ãããåºå®å¤ã§ 1 ãã£ã³ãã«åæã«ãªã£ã¦ãã¾ãã...ã
... public class MicrophoneRecorder : MonoBehaviour { ... public void OnEnd() { if (!audioSource) return; var freq = microphoneWebGL.selectedDevice.sampleRate; _clip = AudioClip.Create( "uMicrophoneWebGL-Recorded", _bufferSize + freq, 1, freq, false); var data = new float[_bufferSize]; System.Array.Copy(_buffer, data, _bufferSize); _clip.SetData(data, 0); } ... }
ããã§æ¬¡ã®ããã«é¸æããããã¤ã¹ãããã£ã³ãã«ãåã£ã¦ããããã«ä¿®æ£ãã¾ãããã®ãã£ã³ãã«ã«ã¦ã³ããåã£ã¦ããæ©è½ã¯ãªãã£ãã®ã§æ¬¡ã®ç¯ã§è¿½å ãã¾ãã
... public void OnEnd() { if (!audioSource) return; var device = microphoneWebGL.selectedDevice; var freq = device.sampleRate; var ch = device.channelCount; _clip = AudioClip.Create( "uMicrophoneWebGL-Recorded", _bufferSize + freq, ch, freq, false); var data = new float[_bufferSize]; System.Array.Copy(_buffer, data, _bufferSize); _clip.SetData(data, 0); } ...
ãã£ã³ãã«ã«ã¦ã³ãã®åå¾
WebGL å´
ãã¦ããã®ãã£ã³ãã«ã«ã¦ã³ããJavaScript å´ã§ã¯æ¬¡ã®ããã«åããããã§ãã
... updateDeviceList: async function() { ... for (const device of this.devices) { ... const source = audioContext.createMediaStreamSource(stream); const audioTrack = stream.getAudioTracks()[0]; const settings = audioTrack.getSettings(); device.sampleRate = settings.sampleRate; device.channelCount = settings.channelCount; ... } ... }, ...
Unity å´
ããããC# çã§ã¯ä½ã¨ãã£ã³ãã«æ°ãåå¾ãã API ããªãããã§ãã
調ã¹ã¦ã¿ã¾ããããæ®å¿µãªãã Unity ã® Microphpone
ã¯ã©ã¹ã§ã¯ããã£ã³ãã«æ°ãåå¾ãã API ããªãããã§ãã次ã®ããã« Microphone.Start()
ãéãã¦å¾ããã AudioClip
çµç±ã§åå¾ã§ããªãããªãã¨æããã£ã¦ã¿ã¾ãããé§ç®ã§ããã
public static int GetChannelCount(int index) { var name = GetDeviceId(index); if (string.IsNullOrEmpty(name)) return 1; var freq = GetSampleRate(index); var audioClip = Microphone.Start(name, false, 10, freq); // å®éã«ãã¤ã¯ãã¹ã¿ã¼ãããã¾ã§å¾ ããªãã¨ãªããªã... int retryCount = 0; while (Microphone.GetPosition(name) <= 0) { if (++retryCount >= 1000) { Debug.LogError("Failed to get microphone."); return 1; } System.Threading.Thread.Sleep(1); } Microphone.End(name); return audioClip.channels; // 常㫠1 ãè¿ã£ã¦ãã¦ãã¾ãæ¨¡æ§ }
次ã«ãåºå® 1 ãã£ã³ãã«ã§å²ãåããã¨ã«ãããã¨æããOnAudioFilterRead(int[] input, int channels)
çµç±ã§åå¾ãã¦ãããããã¡ãéå¼ãã¦ä½¿ããã¨æ¬¡ã®ãããªã³ã¼ããæ¸ãã¦ã¿ã¾ããã
void OnAudioFilterRead(float[] input, int channels) { lock (_lock) { int n = input.Length / channels; if (_bufferSize + n >= _buffer.Length) return; if (channels > 1) { for (int i = 0; i < n; ++i) { _buffer[_bufferSize + i] = input[i * channels]; } } else { System.Array.Copy(input, 0, _buffer, _bufferSize, n); } _bufferSize += n; } if (!playMicrophoneSound) { System.Array.Clear(input, 0, input.Length); } }
ããããªãããããã ã¨æ¯å channels = 2 ã¨ãªã£ã¦ãã¾ããéã« Mac ã®å èµãã¤ã¯ã®ãããªã¢ãã®ããã¤ã¹ã§ããããé«ããªã£ã¦ãã¾ãã¾ãã...ããããããªãã®ã§æ®å¿µãªãããããã°ç¨ã« Preference ãããæåã§ãæ°å¤ãå ¥åãã¦ãããå½¢å¼ã«ãã¾ããã
ãã®æ°åã使ã£ã¦ä¸è¨ã® OnAudioFilterRead()
ã§ã¹ããããããã£ã³ãã«æ°ãæå®ãããã¨ããæ¹å¼ã¨ãªã£ã¦ãã¾ãã
ãã®ä»ãã°ä¿®æ£
ã¤ãã§ã«ãã°ä¿®æ£ãã¾ãããããã¾ã§ãWebGL å´ã§é¸æãããã¤ã¯ã§é©åã«é²é³ã§ãã¦ãã¾ããã§ããâ¦ï¼ããã©ã«ãã®ãã¤ã¯ã常ã«æå®ããã¦ãã¾ã£ã¦ãã¾ããï¼ã
ãããã«
ã¯ã©ã¹ãã©ãããã©ã¼ã ãèæ ®ãã¤ã¤ããã¤ã²ã¼ã ã¨ã³ã¸ã³ã¨ãã¦ã¯ããã¤ã¯ã®å ¥åãã£ã³ãã«æ°ã¯ã¾ã確ãã«éè¦ã§ã¯ãªãã®ã§ API ããªãã®ã¯æ®å¿µã§ããç解ãã¾ãããã¯ã¼ã¯ã¢ã©ã¦ã³ãã¯ç¨æã§ããã®ã§ã²ã¨ã¾ãè¯ãã¨ãã¾ãã