AndroidでMicrophoneで音声取得して周波数別に分解する方法です。まずコードを書くと以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
using UnityEngine; using System.Collections; using UnityEngine.UI; [RequireComponent(typeof(AudioSource))] public class BuzzerEventScript : MonoBehaviour { public GameObject[] cube; public int[] Hertz; public float MeterFactor = 1; public float BUZZER_HZ_MIN; public int BUZZER_REPEAT_MIN; private float[] _spectrum = new float[1024 * 8]; private AudioSource audio; private float[] values; void Start() { audio = GetComponent<AudioSource>(); // Microphone // 引数は、デバイス名(null ならデフォルト)、ループ、何秒取るか、サンプリング周波数 audio.clip = Microphone.Start(null, true, 999, 44100); while (Microphone.GetPosition(null) <= 0) { } audio.Play(); } void Update() { audio.GetSpectrumData(_spectrum, 0, FFTWindow.BlackmanHarris); values = new float[cube.Length]; for (int i = 0; i < _spectrum.Length; ++i) { var freq = ((AudioSettings.outputSampleRate * 0.5) / _spectrum.Length) * i; var idx = SpectrumToIndex((int)freq); if (idx >= 0) { values[idx] = Mathf.Max(_spectrum[i], values[idx]); } } for (int i = 0; i < cube.Length; ++i) { float meterValue = System.Math.Min(1.0f, values[i] * int.Parse(MeterFactorInput.text)); cube[i].transform.localScale = new Vector3(cube[i].transform.localScale.x, meterValue, cube[i].transform.localScale.z); } } int SpectrumToIndex(int freq) { for (int n = 0; n < Hertz.Length; n++) { if (Hertz[n] > freq) { return n; } } return -1; } } |
audio.Play(); で録音と同時に再生もしますのでハウリングが起こります。探すとサイトによっては audio.mute = true; で再生しても音がならないとありましたが録音してくれず…。このコードを書いた時はテスト段階だったためとりあえず端末の音を0にして作業しました。
上のようにSceneにCubeを20個並べてその長さが変更するようになっています。
参考
http://tips.hecomi.com/entry/2014/11/11/021147
http://kikikiroku.session.jp/unity5-audio-levelmeter/
0 Comments
1 Pingback