如何使用 swift 监控 ios 上的音频输入 - 示例?

问题描述 投票:0回答:3

我想编写一个简单的应用程序,当麦克风的声级达到一定水平时,它会“做一些事情”,显示音频输入级别以获得额外的积分

无法在 swift 中找到任何达到此目的的示例 - 不想记录,只是监视

一直在查看 AVFoundation 类的文档,但无法起步

谢谢

ios swift avfoundation
3个回答
3
投票

让您可以使用以下代码:

func initalizeRecorder ()
 {
    do {

        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
        try AVAudioSession.sharedInstance().setActive(true)

    }catch{
        print(error);
    }


    let stringDir:NSString = self.getDocumentsDirectory();
    let audioFilename = stringDir.stringByAppendingPathComponent("recording.m4a")
    let audioURL = NSURL(fileURLWithPath: audioFilename)
    print("File Path : \(audioFilename)");

    // make a dictionary to hold the recording settings so we can instantiate our AVAudioRecorder

    let settings = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 12000.0,
        AVNumberOfChannelsKey: 1 as NSNumber,
        AVEncoderBitRateKey:12800 as NSNumber,
        AVLinearPCMBitDepthKey:16 as NSNumber,
        AVEncoderAudioQualityKey: AVAudioQuality.High.rawValue
    ]



do {
        if audioRecorder == nil
        {
            audioRecorder = try AVAudioRecorder(URL: audioURL, settings: settings )
            audioRecorder!.delegate = self
            audioRecorder!.prepareToRecord();
            audioRecorder!.meteringEnabled = true;
        }
        audioRecorder!.recordForDuration(NSTimeInterval(5.0));
     } catch {
        print("Error")
    }

 }

//GET DOCUMENT DIR PATH
 func getDocumentsDirectory() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0]
    return documentsDirectory
}
////START RECORDING
@IBAction func btnStartPress(sender: AnyObject) {

    recordingSession = AVAudioSession.sharedInstance()
    do {


        recordingSession.requestRecordPermission() { [unowned self] (allowed: Bool) -> Void in
            dispatch_async(dispatch_get_main_queue()) {
                if allowed {
                 print("Allowd Permission Record!!")
                    self.initalizeRecorder ()
                    self.audioRecorder!.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)

                } else {
                    // failed to record!
                    self.showPermissionAlert();
                    print("Failed Permission Record!!")
                }
            }
        }
    } catch {
        // failed to record!
        print("Failed Permission Record!!")
    }

}


    //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
    if audioRecorder != nil
    {
        audioRecorder!.updateMeters()

        let ALPHA : Double = 0.05;
        let peakPowerForChannel : Double = pow(Double(10.0), (0.05) * Double(audioRecorder!.peakPowerForChannel(0)));
        lowPassResults = ALPHA * peakPowerForChannel + Double((1.0) - ALPHA) * lowPassResults;
        print("low pass res = \(lowPassResults)");
        if (lowPassResults > 0.7 ){
           print("Mic blow detected");
           }
       }


 }
     //STOP RECORDING
    @IBAction func btnStopPress(sender: AnyObject) {

            if audioRecorder != nil
            {
                audioRecorder!.stop()
                self.levelTimer.invalidate()
            }

        }

0
投票

AVAudioRecorder
中您可以“录制音频”(不必保存)并设置
meteringEnabled
以使用该功能
peakPowerForChannel(_:)

会的

返回给定通道所录制声音的峰值功率(以分贝为单位)。

此链接可能提供示例代码

如果对您有帮助,请告诉我。


0
投票

@JayMehta 的代码,已更新至 Xcode 15.0

import UIKit
import AVFoundation
import DGCharts

struct Constants {
    static let sampleTime = 0.02  // time between peak power calculations - seconds
    static let filterTimeConstant = 0.4  // time to reach 63% of input - seconds
    static let ALPHA = 1 - exp(-sampleTime / filterTimeConstant)  // zero-order hold low-pass filter coefficient
}

class ViewController: UIViewController, AVAudioRecorderDelegate {
    
    var audioRecorder: AVAudioRecorder?
    var levelTimer = Timer()
    var lowPassResults = 0.0
    
    func initializeRecorder() {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
            try AVAudioSession.sharedInstance().setActive(true)
        } catch {
            print(error)
        }
        
        let stringDir = NSString(string: self.getDocumentsDirectory())
        let audioFilename = stringDir.appendingPathComponent("recording.m4a")
        let audioURL = URL(fileURLWithPath: audioFilename)
        print("File Path: \(audioFilename)")
        
        // make a dictionary to hold the recording settings so we can instantiate our AVAudioRecorder
        let settings: [String : Any] = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 12000.0,
            AVNumberOfChannelsKey: 1 as NSNumber,
            AVEncoderBitRateKey: 12800 as NSNumber,
            AVLinearPCMBitDepthKey: 16 as NSNumber,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]
        
        do {
            if audioRecorder == nil {
                audioRecorder = try AVAudioRecorder(url: audioURL, settings: settings)
                audioRecorder!.delegate = self
                audioRecorder!.isMeteringEnabled = true
                audioRecorder!.prepareToRecord()
            }
            audioRecorder!.record(forDuration: TimeInterval(5.0))
        } catch {
            print("Error")
        }
    }
    
    // GET DOCUMENT DIR PATH
    func getDocumentsDirectory() -> String {
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0]
        return documentsDirectory
    }
    
    // START RECORDING
    @IBAction func btnStartPress(sender: AnyObject) {
        
        AVAudioApplication.requestRecordPermission() { [unowned self] allowed in
            if allowed {
                print("Allowed permission to record!")
                initializeRecorder()
                audioRecorder!.record()
                
                // instantiate a timer to be called with whatever frequency we want to grab metering values
                levelTimer = Timer.scheduledTimer(timeInterval: Constants.sampleTime, target: self, selector: #selector(levelTimerCallback), userInfo: nil, repeats: true)
                
            } else {
                // failed to record!
//                showPermissionAlert()
                print("Failed permission to record!")
            }
        }
    }
    
    // This selector/function is called every time our timer (levelTime) fires
    @objc func levelTimerCallback() {
        // we have to update meters before we can get the metering values
        audioRecorder!.updateMeters()
        
        let peakPowerForChannel = pow(10, 0.05 * Double(audioRecorder!.peakPower(forChannel: 0)))
        lowPassResults = Constants.ALPHA * peakPowerForChannel + (1 - Constants.ALPHA) * lowPassResults
        print("low pass results = \(lowPassResults)")
        if lowPassResults > 0.7 {
            print("threshold exceeded")
        }
    }
    
    // STOP RECORDING
    @IBAction func btnStopPress(sender: AnyObject) {
        audioRecorder!.stop()
        levelTimer.invalidate()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.