*目次 #contents() ADX2LEでマイク入力レベルを得るテスト (かなり雑ですが・・・とりあえず) *MaicInputTest.mm // ADX2LEでマイク入力レベルを得るテスト // Plugins/iOSに保存して使う // 参考サイト:http://blog.koogawa.com/entry/2013/11/24/121807 extern "C" { void StartUpdatingVolume_(); float GetPeakPower_(); void StopUpdatingVolume_(); } #import <AudioToolbox/AudioToolbox.h> #import <AVFoundation/AVFoundation.h> @interface MicInputTest :NSObject//UIViewController// :NSObject //: UnityAppController @end @implementation MicInputTest AudioQueueRef _queue; // 音声入力用のキュー NSTimer *_timer; // 監視タイマー static void AudioInputCallback( void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) { // 録音はしないので未実装 } /* - (void)preStartUnity { // 音を拾う [self startUpdatingVolume]; }*/ /* - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } */ bool initFlag = false; - (void)startUpdatingVolume { NSLog(@"#startUpdatingVolume"); if(initFlag == false){ AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *err = nil; [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err]; if(err){ NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]); return; } [audioSession setActive:YES error:&err]; err = nil; if(err){ NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]); return; } } // 記録するデータフォーマットを決める AudioStreamBasicDescription dataFormat; dataFormat.mSampleRate = 44100.0f; dataFormat.mFormatID = kAudioFormatLinearPCM; dataFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; dataFormat.mBytesPerPacket = 2; dataFormat.mFramesPerPacket = 1; dataFormat.mBytesPerFrame = 2; dataFormat.mChannelsPerFrame = 1; dataFormat.mBitsPerChannel = 16; dataFormat.mReserved = 0; // レベルの監視を開始する AudioQueueNewInput(&dataFormat, AudioInputCallback, (__bridge void *)(self), CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &_queue); AudioQueueStart(_queue, NULL); // レベルメータを有効化する UInt32 enabledLevelMeter = true; AudioQueueSetProperty(_queue, kAudioQueueProperty_EnableLevelMetering, &enabledLevelMeter, sizeof(UInt32)); /* // 定期的にレベルメータを監視する _timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(detectVolume:) userInfo:nil repeats:YES]; */ } - (void)stopUpdatingVolume { // キューを空にして停止 AudioQueueFlush(_queue); AudioQueueStop(_queue, NO); AudioQueueDispose(_queue, YES); } /* - (void)detectVolume:(NSTimer *)timer { // レベルを取得 AudioQueueLevelMeterState levelMeter; UInt32 levelMeterSize = sizeof(AudioQueueLevelMeterState); AudioQueueGetProperty(_queue, kAudioQueueProperty_CurrentLevelMeterDB, &levelMeter, &levelMeterSize); NSLog(@"%.2f", levelMeter.mPeakPower); // 最大レベル、平均レベルを表示 //self.peakTextField.text = [NSString stringWithFormat:@"%.2f", levelMeter.mPeakPower]; //self.averageTextField.text = [NSString stringWithFormat:@"%.2f", levelMeter.mAveragePower]; // mPeakPowerが -1.0 以上なら "LOUD!!" と表示 //self.loudLabel.hidden = (levelMeter.mPeakPower >= -1.0f) ? NO : YES; }*/ MicInputTest* ma; void StartUpdatingVolume_() { NSLog(@"#StartUpdatingVolume_"); ma = [[MicInputTest alloc] init]; [ma startUpdatingVolume]; } float GetPeakPower_() { // レベルを取得 AudioQueueLevelMeterState levelMeter; UInt32 levelMeterSize = sizeof(AudioQueueLevelMeterState); AudioQueueGetProperty(_queue, kAudioQueueProperty_CurrentLevelMeterDB, &levelMeter, &levelMeterSize); NSLog(@"%.2f %.2f", levelMeter.mPeakPower,levelMeter.mAveragePower); return levelMeter.mPeakPower; } void StopUpdatingVolume_() { NSLog(@"#StopUpdatingVolume"); if(ma != nil) { [ma stopUpdatingVolume]; } } @end *MicTest.cs // GameObjectに貼付ける。画面タップするとレベルが取得できるようになる。 using UnityEngine; using System.Collections; using System.Runtime.InteropServices; public class MicTest : MonoBehaviour { [DllImport("__Internal")] private static extern void StartUpdatingVolume_(); public static void StartUpdatingVolume() { if (Application.platform != RuntimePlatform.OSXEditor) { StartUpdatingVolume_(); } } [DllImport("__Internal")] private static extern void StopUpdatingVolume_(); public static void StopUpdatingVolume() { if (Application.platform != RuntimePlatform.OSXEditor) { StopUpdatingVolume_(); } } [DllImport("__Internal")] private static extern float GetPeakPower_(); public static float GetPeakPower() { if (Application.platform != RuntimePlatform.OSXEditor) { return GetPeakPower_(); } return 0.0f; } public TextMesh tm; public static MicTest main = null; void Awake() { if(main != null) { GameObject.Destroy(this); } else { main = this; } } // Use this for initialization void Start () { } void OnDestroy() { MicTest.StopUpdatingVolume(); micEnable = false; initFlag = false; } void OnApplicationPause(bool pause) { MicTest.StopUpdatingVolume(); micEnable = false; initFlag = false; } float level = 0.0f; public float volumInputGain = 10.0f; public float GetVolumeLevel() { return level; } public float time = 0; float lastVolume = 0f; bool micEnable = false; bool initFlag = false; // Update is called once per frame void Update () { if(Input.GetMouseButton(0)){ if(micEnable == false){ micEnable = true; } } if(micEnable){ if(initFlag == false){ MicTest.StartUpdatingVolume(); /* AudioSource audioSource = this.gameObject.AddComponent<AudioSource>(); audio.clip = Microphone.Start(null, true, 999, 44100); // マイクからのAudio-InをAudioSourceに流す audio.loop = true; // ループ再生にしておく audio.mute = true; // マイクからの入力音なので音を流す必要がない while (!(Microphone.GetPosition("") > 0)){} // マイクが取れるまで待つ。空文字でデフォルトのマイクを探してくれる audio.Play(); */ initFlag = true; } if(initFlag){ /* float vol = GetAveragedVolume(); lastVolume = Mathf.Lerp(lastVolume, vol, Time.time*0.001f); level = vol*volumInputGain; */ tm.text = MicTest.GetPeakPower().ToString();//level.ToString(); } } } float GetAveragedVolume() { float[] data = new float[256]; float a = 0; audio.GetOutputData(data,0); foreach(float s in data) { a += Mathf.Abs(s); } return a/256.0f; } }