我需要快速开发一个iOS应用程序,以检测用户的麦克风是否受到打击。这必须是一个挑战游戏,其中两个玩家必须一个接一个地吹入iPhone麦克风。分贝值应以米或公里为单位进行测量和换算,以便我确定获胜者。“进一步打击”的玩家(玩家1:50公里,玩家2:70公里)获胜。
这可能吗?
我很快就收到了这段代码,但我不知道如何进行:
import Foundation import UIKit import AVFoundation import CoreAudio class ViewController: UIViewController { // @IBOutlet weak var mainImage: UIImageView! var recorder: AVAudioRecorder! var levelTimer = NSTimer() var lowPassResults: Double = 0.0 override func viewDidLoad() { super.viewDidLoad() let url = NSURL.fileURLWithPath("dev/null") //numbers are automatically wrapped into NSNumber objects, so I simplified that to [NSString : NSNumber] var settings : [NSString : NSNumber] = [AVSampleRateKey: 44100.0, AVFormatIDKey: kAudioFormatAppleLossless, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.Max.rawValue] var error: NSError? // mainImage?.image = UIImage(named: "flyForReal.png"); recorder = AVAudioRecorder(URL:url, settings:settings, error:&error) if((recorder) != nil){ recorder.prepareToRecord() recorder.meteringEnabled = true recorder.record() levelTimer = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: Selector("levelTimerCallback"), userInfo: nil, repeats: true) } else{ NSLog("%@", "Error"); } } func levelTimerCallback(timer:NSTimer) { recorder.updateMeters() let ALPHA: Double = 0.05 var peakPowerForChannel = pow(Double(10), (0.05 * Double(recorder.peakPowerForChannel(0)))) lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; if(lowPassResults > 0.95){ NSLog("@Mic blow detected"); } NSLog("@Average input: %f Peak input: %f Low pass results: %f", recorder.averagePowerForChannel(0), recorder.peakPowerForChannel(0), lowPassResults); } }
谢谢你!
关。您有几个问题。您的选择器调用使该应用程序崩溃,因为您没有传递参数并且levelTimerCallback()需要一个参数。
levelTimerCallback()
averagePowerPerChannel 似乎给了我更实时的测光,所以我用它代替了 peakPowerPerChannel
averagePowerPerChannel
peakPowerPerChannel
另外,您需要设置音频会话。我不确定那个数学到底是什么,所以我在这里摆脱了它。我在下面粘贴了整个视图控制器,以进行基本的麦克风检测。
import Foundation import UIKit import AVFoundation import CoreAudio class ViewController: UIViewController { var recorder: AVAudioRecorder! var levelTimer = NSTimer() var lowPassResults: Double = 0.0 override func viewDidLoad() { super.viewDidLoad() //make an AudioSession, set it to PlayAndRecord and make it active var audioSession:AVAudioSession = AVAudioSession.sharedInstance() audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil) audioSession.setActive(true, error: nil) //set up the URL for the audio file var documents: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] var str = documents.stringByAppendingPathComponent("recordTest.caf") var url = NSURL.fileURLWithPath(str as String) // make a dictionary to hold the recording settings so we can instantiate our AVAudioRecorder var recordSettings: [NSObject : AnyObject] = [AVFormatIDKey:kAudioFormatAppleIMA4, AVSampleRateKey:44100.0, AVNumberOfChannelsKey:2,AVEncoderBitRateKey:12800, AVLinearPCMBitDepthKey:16, AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue ] //declare a variable to store the returned error if we have a problem instantiating our AVAudioRecorder var error: NSError? //Instantiate an AVAudioRecorder recorder = AVAudioRecorder(URL:url, settings: recordSettings, error: &error) //If there's an error, print that shit - otherwise, run prepareToRecord and meteringEnabled to turn on metering (must be run in that order) if let e = error { println(e.localizedDescription) } else { recorder.prepareToRecord() recorder.meteringEnabled = true //start recording recorder.record() //instantiate a timer to be called with whatever frequency we want to grab metering values self.levelTimer = NSTimer.scheduledTimerWithTimeInterval(0.02, target: self, selector: Selector("levelTimerCallback"), userInfo: nil, repeats: true) } } //This selector/function is called every time our timer (levelTime) fires func levelTimerCallback() { //we have to update meters before we can get the metering values recorder.updateMeters() //print to the console if we are beyond a threshold value. Here I've used -7 if recorder.averagePowerForChannel(0) > -7 { print("Dis be da level I'm hearin' you in dat mic ") println(recorder.averagePowerForChannel(0)) println("Do the thing I want, mofo") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }