2015-07-05 13 views
7

Tôi cần phát triển ứng dụng iOS nhanh chóng phát hiện một cú đánh trong micrô từ người dùng. Đây phải là một trò chơi Thách thức, trong đó hai người chơi phải thổi vào micrô iPhone sau cái kia. Các giá trị decibel cần được đo và chuyển đổi theo đơn vị mét hoặc ki lô mét để tôi có thể xác định người chiến thắng. Người chơi "thổi thêm" (player1: 50km, player2: 70km) sẽ thắng.iOS - Phát hiện Blow thành Mic và chuyển đổi kết quả! (nhanh chóng)

Đây có phải là triển khai có thể không?

Tôi có mã này trong nhanh chóng và tôi không biết làm thế nào để tiến hành:

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); 
} 
} 

Cảm ơn trước!

Trả lời

9

Đóng. Bạn có một vài vấn đề. Cuộc gọi chọn của bạn làm treo ứng dụng vì bạn không chuyển đối số và levelTimerCallback() sẽ là một đối số.

averagePowerPerChannel dường như để cho tôi một đo thời gian thực hơn vì vậy tôi sử dụng mà thay vì peakPowerPerChannel

Ngoài ra, bạn cần phải thiết lập một phiên âm thanh. Tôi đã không thực sự chắc chắn tất cả những gì toán học đã được về, vì vậy tôi chỉ cần thoát khỏi nó ở đây. Tôi đã dán toàn bộ bộ điều khiển xem bên dưới để phát hiện mic cơ bản.

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. 
} 


} 
3

Tôi đã chuyển câu trả lời của Andrew thành Swift 4 và nó hoạt động tuyệt vời! Cảm ơn!

import Foundation 
import UIKit 
import AVFoundation 
import CoreAudio 

class ViewController: UIViewController { 

    var recorder: AVAudioRecorder! 
    var levelTimer = Timer() 

    let LEVEL_THRESHOLD: Float = -10.0 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let documents = URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]) 
     let url = documents.appendingPathComponent("record.caf") 

     let recordSettings: [String: Any] = [ 
      AVFormatIDKey:    kAudioFormatAppleIMA4, 
      AVSampleRateKey:   44100.0, 
      AVNumberOfChannelsKey:  2, 
      AVEncoderBitRateKey:  12800, 
      AVLinearPCMBitDepthKey:  16, 
      AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue 
     ] 

     let audioSession = AVAudioSession.sharedInstance() 
     do { 
      try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord) 
      try audioSession.setActive(true) 
      try recorder = AVAudioRecorder(url:url, settings: recordSettings) 

     } catch { 
      return 
     } 

     recorder.prepareToRecord() 
     recorder.isMeteringEnabled = true 
     recorder.record() 

     levelTimer = Timer.scheduledTimer(timeInterval: 0.02, target: self, selector: #selector(levelTimerCallback), userInfo: nil, repeats: true) 

    } 

    @objc func levelTimerCallback() { 
     recorder.updateMeters() 

     let level = recorder.averagePower(forChannel: 0) 
     let isLoud = level > LEVEL_THRESHOLD 

     // do whatever you want with isLoud 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


} 
Các vấn đề liên quan