Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS: AVAudioSession not working

I am trying to use AVAudioSession, but it is throwing this runtime error: [avas] AVAudioSessionPortImpl.mm:56:ValidateRequiredFields:Unknown selected data source for Port Speaker (type Speaker). If it helps I am trying to just record audio, and monitor the current decibels. I set the category to AVAudioSessionCategoryRecord, and the mode to AVAudioSessionModeMeasurement. here is the code:

class ViewController: UIViewController {

    let captureSession = AVCaptureSession()
    var recording = false;
    var ready = false;

    let audioSession = AVAudioSession.sharedInstance()

    @IBOutlet public weak var dBLabel: UILabel!

    func alert(title: String, message: String = "", handler: ((UIAlertAction) -> Swift.Void)? = nil) -> Void {
        var usedMessage: String
        if(message.characters.count < 1) {
            usedMessage = title;
        } else {
            usedMessage = message;
        }
        let alert = UIAlertController(title: title, message: usedMessage, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: handler))
        self.present(alert, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func checkPermission()
    {
        switch AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeAudio)
        {
        case .authorized:
            NSLog("Authorized for Microphone Use")

        case .notDetermined:
            AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler: { granted in
                self.checkPermission()
            })

        case .denied:
            let alert = UIAlertController(title: "Denied Access to Microphone", message: "You denied access to the microphone, please enable access in settings", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Go to Settings", style: .default, handler: { _ in
                guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                    return
                }

                if UIApplication.shared.canOpenURL(settingsUrl) {
                    UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                    })
                }
            }))
            alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel"), style: .cancel, handler: nil))
            self.present(alert, animated: true, completion: nil)


        case .restricted:
            alert(title: "Restricted",message: "You cannot enable the microphone, so you cannot use the app", handler: { _ in
                NSLog("The \"OK\" alert occured.")
            })
        }
    }

    @IBAction func toggleRecord(_ sender: UIButton) {
        if(!ready)
        {return}

        NSLog("Toggled Recording")
        recording = !recording;
        if(recording)
        {
            sender.setImage(UIImage(named: "MicIconHighlighted.png"), for: .normal)
            sender.setImage(UIImage(named: "MicIconHighlightedSelected.png"), for: .highlighted)
            //captureSession.startRunning()
            do
            {
                try audioSession.setActive(true)
            } catch {
                NSLog("Activating AudioSession Failed")
            }
        } else {
            sender.setImage(UIImage(named: "MicIcon.png"), for: .normal)
            sender.setImage(UIImage(named: "MicIconSelected.png"), for: .highlighted)
            //captureSession.stopRunning()
            do
            {
                try audioSession.setActive(false)
            } catch {
                NSLog("Deactivating AudioSession Failed")
            }
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        checkPermission()
        do
        {
            try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        } catch {
            NSLog("Setting category on AudioSession failed")
        }

        do
        {
            try audioSession.setMode(AVAudioSessionModeMeasurement)
        } catch {
            NSLog("Setting mode on AudioSession failed")
        }

        do
        {
            try audioSession.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
        } catch {
            NSLog("Failed Setting Audio Output Data Source")
        }


        //NSLog("debug info: \(audioSession.outputDataSources!.count)");

        /*captureSession.beginConfiguration()
        let audioDeviceInput: AVCaptureDeviceInput
        let audioDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)
        if(audioDevice != nil && (audioDevice?.isConnected)!) {
            NSLog("Audio Device Name: \(audioDevice!.localizedName)")
        } else {
            NSLog("AVCapture Device default audio device failed or device not connected")
        }

        do {
            audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)
        } catch {
            alert(title: "Failed to create Capture Device",message: "Failed to create Capture Device", handler: nil)
            return
        }

        if(captureSession.canAddInput(audioDeviceInput))
        {
            captureSession.addInput(audioDeviceInput)
        } else {
            alert(title: "Failed to Add Input",message: "Failed to add Audio Input Device", handler: nil)
        }

        let audioOutput = AVCaptureAudioDataOutput()
        var audioRecorder = AVAudioRecorder()
        audioRecorder.
        var audioQueue = DispatchQueue(label: "audioqueue", attributes: .concurrent)
        audioOutput.setSampleBufferDelegate(AudioOutputSampleBufferDelegate(vc: self), queue: audioQueue)
        NSLog("Current Queue: \(audioOutput.sampleBufferCallbackQueue.description)")
        if(captureSession.canAddOutput(audioOutput))
        {
            captureSession.addOutput(audioOutput)
            captureSession.commitConfiguration()
        } else {
        alert(title: "Failed to Add Output",message: "Failed to add Audio Output Device", handler: nil)
        }*/

        ready = true
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
like image 640
Codekrafter Avatar asked Aug 10 '18 17:08

Codekrafter


1 Answers

AVAudioSession has some changes in Swift 4.2

under viewDidAppear(), try this:

    // Prepare Audio Session
    self.audioSession = AVAudioSession.sharedInstance()

    try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .measurement, options: .defaultToSpeaker)
    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)

It worked for me when I converted the language to Swift 4.2 in Xcode 10 You can do that by going to...

Edit, Convert, To Current Swift Syntax...

like image 121
Farini Avatar answered Sep 18 '22 17:09

Farini