iqra
iqra

Reputation: 1261

Watch OS : Microphone & Audio Processing

Is it possible to access the watch microphone and process the live audio stream to gain specific information (decibel level & current frequency)? I know it's possible to record audio on the watch by using the swift presentAudioRecorderController. However, I do not want to present the default voice memo UI that comes with it. And even I do use this, it does not give access to the live stream to play around with. Instead, I want to continuously and silently listen in the background.

Upvotes: 2

Views: 1007

Answers (1)

Zsombor Fuszenecker
Zsombor Fuszenecker

Reputation: 161

You can certainly record using the watch only. Just remember to add the corresponding NSMicrophoneUsageDescription into the plist.

Here is some code that can get you started. You can then get the average power from the audioRecorder and use that for making some magic on the UI.

    func startRecording () {
        if isRecording {
            recordButton.setBackgroundImage(UIImage(named: "stopImage"))
            let fileGuid = "\(UUID().uuidString)s.m4a"
            let audioFilename = getDocumentsDirectory().appendingPathComponent(fileGuid)
            fileOutputPath = audioFilename

            let audioSession = AVAudioSession.sharedInstance()
            do {
                try audioSession.setCategory(category, mode: .spokenAudio)
            } catch let sessionError {}

            let settings: [String: Int] = [
                AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
                AVSampleRateKey: 48000,
                AVEncoderBitRateKey: 256000,
                AVNumberOfChannelsKey: 2,
                AVEncoderAudioQualityKey: .max
            ]

            do {
                audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
                audioRecorder?.prepareToRecord()
                audioRecorder?.isMeteringEnabled = true
                audioRecorder?.record()
            } catch {}
        } else {
            recordButton.setBackgroundImage(UIImage(named: "recordImage"))
            do {
                try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
            } catch let sessionError {
                print(sessionError)
            }
            audioRecorder?.stop()
            send()
        }
    }

    func send() {
        // waking app if its not running in the background
        session.sendMessage(["wake": "up"], replyHandler: { _ in
            self.session.transferFile(self.fileOutputPath, metadata: nil)
        }, errorHandler: { _ in
            // waking up device failed. Still, we should try putting the file into the queue so it eventually gets synced to the device
            self.session.transferFile(self.fileOutputPath, metadata: nil)
        })
    }

Upvotes: 2

Related Questions