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