ADX2LEでマイク入力

「ADX2LEでマイク入力」の編集履歴(バックアップ)一覧に戻る

ADX2LEでマイク入力 - (2015/01/09 (金) 18:47:33) のソース

*目次
#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;
		}
	}