Now that Unity iPhone 1.5 is out, is it possible to get mic input from within Unity? Is it only possible through a custom native plugin? If so, any pointers on where to start? thanks.
The first question I would ask is what are you trying to do? Do you just want to record a short audio clip or are you after speech recognition and T-Pain effects?
I'm really just wanting to monitor the mic's input level... such that certain gameobjects in unity respond to how loud the user speaks/whistles/blows/whatever into the mic.
OK, so how about a customer object that opens and monitors the wave input stream. It could keep a small buffer that it would use to calculate the magnitude of the audio. The object would have init, shutdown and getMagnatude calls. Something like that?
I think I could use this Obj-C code (http://www.mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/) and call it using Unity iPhone Pro's native plugin ability. But I was hoping there was an easier way.
Randy: give this a try. It's based on Dan's code. You can get the raw mic level, or the mic level with the low-pass filter. I haven't had time to test it, but it does compile. C#: Code (csharp): [DllImport ("__Internal")] public static extern void SB_startMicLevel(); [DllImport ("__Internal")] public static extern void SB_stopMicLevel(); [DllImport ("__Internal")] public static extern float SB_getMicLevel(); [DllImport ("__Internal")] public static extern float SB_getMicLowPassFiltered(); Objective-C++: Code (csharp): // // SBMicLevel.mm // Unity-iPhone // // Created by Rob Terrell on 8/26/09. // Copyright 2009 Stinkbot LLC. All rights reserved. // #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h> AVAudioRecorder* recorder; float lowPassResults; extern "C" void SB_startMicLevel() { NSURL *url = [NSURL fileURLWithPath:@"/dev/null"]; NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat: 44100.0], AVSampleRateKey, [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey, [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, [NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey, nil]; NSError *error; recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error]; if (recorder) { [recorder prepareToRecord]; recorder.meteringEnabled = YES; [recorder record]; } else { NSLog([error description]); } } extern "C" float SB_getMicLevel() { if (! recorder) SB_startMicLevel(); if (recorder) { [recorder updateMeters]; return [recorder peakPowerForChannel:0]; } return -1; } extern "C" float SB_getMicLowPassFiltered() { if (recorder) { [recorder updateMeters]; const double ALPHA = 0.05; float peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; return lowPassResults; } return -1; } extern "C" void SB_stopMicLevel() { [recorder release]; recorder = nil; }
I played around with the AVAudioRecorder, but it was always saying the output was around -120db regardless of what I was doing (this is on an iPhone with 3.0 installed). Maybe I need to change the audio session category? I'm not sure the way Unity handles its audio or if it would conflict with that particular class.
I tried to build and run the code above, and I can get it to compile and build in Unity, but I get the following error during the linking: Code (csharp): Building target “Unity-iPhone” of project “Unity-iPhone” with configuration “Release” — (5 errors) cd "/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope" setenv IPHONEOS_DEPLOYMENT_TARGET 3.1 setenv MACOSX_DEPLOYMENT_TARGET 10.5 setenv PATH "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++-4.2 -arch armv6 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk "-L/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/build" "-L/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope" "-L/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/Libraries" "-F/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/build" -filelist "/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/build/Unity-iPhone.build/Release-iphoneos/Unity-iPhone.build/Objects-normal/armv6/sample.LinkFileList" -mmacosx-version-min=10.5 -Wl,-dead_strip -Wl,-S,-x -miphoneos-version-min=3.1 -framework Foundation -framework UIKit -framework OpenGLES -framework QuartzCore -framework OpenAL -liconv.2 -liPhone-lib -framework AudioToolbox -framework CFNetwork -framework MediaPlayer -framework CoreLocation -framework SystemConfiguration -o "/Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/build/sample.app/sample" Undefined symbols: "_AVFormatIDKey", referenced from: _AVFormatIDKey$non_lazy_ptr in MicInput.o "_AVSampleRateKey", referenced from: _AVSampleRateKey$non_lazy_ptr in MicInput.o "_AVNumberOfChannelsKey", referenced from: _AVNumberOfChannelsKey$non_lazy_ptr in MicInput.o "_AVEncoderAudioQualityKey", referenced from: _AVEncoderAudioQualityKey$non_lazy_ptr in MicInput.o "_OBJC_CLASS_$_AVAudioRecorder", referenced from: __objc_classrefs__DATA@0 in MicInput.o ld: symbol(s) not found collect2: ld returned 1 exit status "_AVFormatIDKey", referenced from: _AVFormatIDKey$non_lazy_ptr in MicInput.o "_AVSampleRateKey", referenced from: _AVSampleRateKey$non_lazy_ptr in MicInput.o "_AVNumberOfChannelsKey", referenced from: _AVNumberOfChannelsKey$non_lazy_ptr in MicInput.o "_AVEncoderAudioQualityKey", referenced from: _AVEncoderAudioQualityKey$non_lazy_ptr in MicInput.o "_OBJC_CLASS_$_AVAudioRecorder", referenced from: __objc_classrefs__DATA@0 in MicInput.o ld: symbol(s) not found collect2: ld returned 1 exit status Build failed (5 errors) There is an EntryPointNotFoundException given in Unity using the code, but I also encountered that with a basic plugin that printed the number 5, and that program built and ran in the phone regardless of the exception, so I'm not sure that its related. (I made that basic plugin just to make sure that I knew how to complete the entire process). Any ideas on what's giving me the issue?
I put in the AVFoundation and CoreAudio frameworks into the project, and I was able to get the errors to go away, only to get it replaced by a new one: Code (csharp): ld: ldr 12-bit displacement out of range (5716 max +/-4096) in _AudioQueueAddPropertyListener$stub in _AudioQueueAddPropertyListener$stub from /Users/Dev1/Downloads/Penelope-1/Tutorial Project/Penelope/build/sample.app/sample After some searching, this topic seems relevant: http://forum.unity3d.com/viewtopic.php?p=202707 Has there been any solution to this issue? If not, are there any workarounds? I need to do some quick prototypes with mic input for my company. Thanks!
I'm currently a Unity iPhone Basic user... Either thru the enhancement pack or not, can I do mic recording? Will I need iPhone Advanced? That's a big jump for one feature (small audio recording) Help? Sumner
I have Unity iPhone Advanced, who can tell me how to put mic plugin into it? Pls help me. :cry: :cry: :cry:
Check out the plugin example project to get a feeling on how these things work and relate to other things.
Hi there, I've got the code from this thread working (thanks for the post btw bliprob!) - however, I hit the same -120 issue as Tetrad. I discovered this was due to the AudioSession.category not being AVAudioSessionCategoryPlayAndRecord, as Unity (understandably) sets it to the best suited to the target iPhone hardware OS. So, I set it to PlayAndRecord, and voila - microphone now working! But, to keep Unity happy, I believe it should be set back to whatever Unity set it to in the first place... so I do that... and it crashes the app, instantly when I call my modified SB_stopMicLevel(). I can't get a debugger connection to stay up long enough to try and diagnose - does anyone have any ideas? Here's my extra bit o' code... (I'm a n00b at Obj-C btw...) As a file global scope variable... Code (csharp): NSString* audioCategory; In SB_startMicLevel() - just before creating the recorder. Code (csharp): AVAudioSession* avSession = [AVAudioSession sharedInstance] ; audioCategory = avSession.category ; [avSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &error] ; Inside SB_stopMicLevel() Code (csharp): NSError *error ; [[AVAudioSession sharedInstance] setCategory: audioCategory error: &error] ; [Edit] BTW - It also crashes if I don't reset the AudioSession.category...
hey, nice catch! Going behind Unity's back with the audio session is a sure source of crashing, I've found. You should probably use the Unity call: Code (csharp): void UnitySetAudioSessionActive(bool active); Call it with NO before you start recording, and YES when you're done. That might work without crashing.
I take no credit - Tetrad was on the case there before me And as he suspected, Unity no likee... Your catch bliprob is a better one yet - but sadly, it still dies. I'm setting it to false before altering the AudioSession and creating the recorder, and enabling it after restoring the session. I've also tried not restoring the session and enabling unity's API... but still no joy I think the two things do not sit well together outside of Unity... we could do with a Unity API to get at the microphone. Has anyone else managed to get the Mic working with Unity?
Hi, is there any solution for this problem? Or is it just not possible to record audio with unity? Please help!
Hi, i just wanna use microphone to know when user blows. Is that possible from unity? I have Unity iphone advanced. Would it be available on Unity3?
I doubt it will be included in Unity 3. It's possible but you're going to have to dig into ObjectiveC and plug ins.
I´ll try to work with plugins. I have the C# code posted here on Unity. I should now include the xcode part on classes, right? Is it possible to run it from unity or it needs to be run on iphone/ipad?
Objective C plug in's only run on the device itself. Do some searching on this forum for iPhone plug in examples and be sure to read the Unity iPhone documentation about creating plug ins. Once you've read the documentation, the first place to start would be to create a simple Objective C application so you can test the mic without involving Unity.
I have this code on Unity C# file: Code (csharp): using UnityEngine; using System.Runtime.InteropServices; public class PruebaAudio : MonoBehaviour { float NIVEL; // Use this for initialization void Start () { SB_startMicLevel(); } // Update is called once per frame void Update () { Debug.Log(SB_getMicLevel().ToString()); } [DllImport ("__Internal")] public static extern void SB_startMicLevel(); [DllImport ("__Internal")] public static extern void SB_stopMicLevel(); [DllImport ("__Internal")] public static extern float SB_getMicLevel(); [DllImport ("__Internal")] public static extern float SB_getMicLowPassFiltered(); } This: Code (csharp): // // SBMicLevel.mm // Unity-iPhone // // Created by Rob Terrell on 8/26/09. // Copyright 2009 Stinkbot LLC. All rights reserved. // #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h> @implementation SBMicLevel AVAudioRecorder* recorder; float lowPassResults; extern "C" void SB_startMicLevel() { NSURL *url = [NSURL fileURLWithPath:@"/dev/null"]; NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat: 44100.0], AVSampleRateKey, [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey, [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, [NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey, nil]; NSError *error; recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error]; if (recorder) { [recorder prepareToRecord]; recorder.meteringEnabled = YES; [recorder record]; } else { NSLog([error description]); } } extern "C" float SB_getMicLevel() { if (! recorder) SB_startMicLevel(); if (recorder) { [recorder updateMeters]; return [recorder peakPowerForChannel:0]; } return -1; } extern "C" float SB_getMicLowPassFiltered() { if (recorder) { [recorder updateMeters]; const double ALPHA = 0.05; float peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0])); lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; return lowPassResults; } return -1; } extern "C" void SB_stopMicLevel() { [recorder release]; recorder = nil; } @end As SBMicLevel.mm And this as SBMicLevel.h Code (csharp): // // SBMicLevel.mm // Unity-iPhone // // Created by Rob Terrell on 8/26/09. // Copyright 2009 Stinkbot LLC. All rights reserved. // #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> #import <CoreAudio/CoreAudioTypes.h> @interface SBMicLevel : NSObject { AVAudioRecorder* recorder; float lowPassResults; } - (void) SB_startMicLevel(); - (float) SB_getMicLevel(); - (float) SB_getMicLowPassFiltered(); - (void) SB_stopMicLevel(); @end I don´t see any error, scene loads but there´s not any Debug on console. Where´s the problem? Where i´m wrong?
Hey. Any chance you could post msparrow's mods as you got them to work? I just tried the c#/c++ combination posted and no luck...maybe you can post the plugin binary and c# you used to invoke? I'm trying to get very simple audio in working... david
Would you care sharing the exact steps you followed to get it to work? And can you answer if this works when developing on Windows as well?
I too just got this working. 1. Follow the code from Bitomule 2. if you dont want to view the readout in the XCode console then add a GUIText lable to your Unity interface and output the result there instead of to Debug.Log 3. In Xcode add the 3 frameworks (Foundation, CoreAudio, AVFoundation) That will now compile (or should) but you will get a constant -120 reading Edit SBMicLevel.mm and under the line Code (csharp): extern "C" void SB_startMicLevel() { Add this Code (csharp): NSError *setCategoryError = nil; [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryError]; if (setCategoryError) { NSLog([setCategoryError description]); } { Now build and run I was getting a readout from 0 to -50 depending on how loud I shouted into the Mic. Anim Unity iPhone Basic
Possibly. You might be able to on a Hackintosh (A pc running OSX) look it up. But be aware its not supported by apple, you would probably need to jail break your iphone to install the app on it and it might still have issues as its mostly community managed not Apple.
Awesome guys, I got it working as a non-programmer, more or less! It appears to get to 0 pretty quickly though - is that because of the code or the hardware? (yes, I love to ask stupid questions...)
Looks awesome but wont work for me :/ Can someone help? Nothing comes in in the console after applicationDidBecomeActive() :/