Search code examples
swiftavaudioplayeravaudiorecorder

Record And Play Voice in Separate Class (Swift3)


I used many codes that was for record an play the voice, but most of them are not in swift3 and they don't work in my app.

This code works, but I want to create a separate class from the viewcontroller that do recording an playing voices. Also the mentioned github code is complex an I'm searching for a simplified code.

Update:

After recording, when I check existence of the recorded file, the file doesn't exist, and it raises EXC_BAD_ACCESS error on appDelegate.

What's wrong?

Any suggestions would be appreciated.


Solution

  • Try to record audio by wirting line

    let isRec = AudioManager.shared.record(fileName: "rec")
    

    if isRec returned true then recording is happening else not. To finish recording use : let recordedURL = AudioManager.shared.finishRecording()

    To play recorded file send above url to setupUpPlayer() function in manager class

    Not to forget to use extension code snippets give below the code snippet which are delegate functions of AVAudioRecorder and AVAudioPlayer

    import Foundation
    
    import AVFoundation
    
    class AudioManager: NSObject {
    
    static let shared = AudioManager()
    
    var recordingSession: AVAudioSession?
    var recorder: AVAudioRecorder?
    var meterTimer: Timer?
    var recorderApc0: Float = 0
    var recorderPeak0: Float = 0
    //PLayer
    var player: AVAudioPlayer?
    var savedFileURL: URL?
    
    func setup() {
        recordingSession = AVAudioSession.sharedInstance()
        do {
            try recordingSession?.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker)
            try recordingSession?.setActive(true)
            recordingSession?.requestRecordPermission({ (allowed) in
                if allowed {
                    print("Mic Authorised")
                } else {
                    print("Mic not Authorised")
                }
            })
        } catch {
            print("Failed to set Category", error.localizedDescription)
        }
    }
    
    func record(fileName: String) -> Bool {
        setup()
        let url = getUserPath().appendingPathComponent(fileName + ".m4a")
        let audioURL = URL.init(fileURLWithPath: url.path)
        let recordSettings: [String: Any] = [AVFormatIDKey: kAudioFormatMPEG4AAC,
                                             AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue,
                                             AVNumberOfChannelsKey: 2,
                                             AVSampleRateKey: 44100.0]
        do {
            recorder = try AVAudioRecorder.init(url: audioURL, settings: recordSettings)
            recorder?.delegate = self
            recorder?.isMeteringEnabled = true
            recorder?.prepareToRecord()
            recorder?.record()
            self.meterTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { (timer: Timer) in
                //Update Recording Meter Values so we can track voice loudness
                if let recorder = self.recorder {
                    recorder.updateMeters()
                    self.recorderApc0 = recorder.averagePower(forChannel: 0)
                    self.recorderPeak0 = recorder.peakPower(forChannel: 0)
                }
            })
            savedFileURL = url
            print("Recording")
            return true
        } catch {
            print("Error Handling", error.localizedDescription)
            return false
        }
    }
    
    func getUserPath() -> URL {
        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    }
    
    func finishRecording() -> String {
        recorder?.stop()
        self.meterTimer?.invalidate()
        var fileURL: String?
        if let url: URL = recorder?.url {
            fileURL = String(describing: url)
        }
        return /fileURL
    }
    //Player
    func setupPlayer(_ url: URL) {
        do {
            try player = AVAudioPlayer.init(contentsOf: url)
        } catch {
            print("Error1", error.localizedDescription)
        }
        player?.prepareToPlay()
        player?.play()
        player?.volume = 1.0
        player?.delegate = self
    }
    }
    

        //MARK:- Audio Recorder Delegate
    
        extension AudioManager: AVAudioRecorderDelegate {
    
        func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
    
            print("AudioManager Finish Recording")
    
        }
        func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
            print("Encoding Error", /error?.localizedDescription)
        }
    
    }
    

        //MARK:- Audio Player Delegates
    
        extension AudioManager: AVAudioPlayerDelegate {
    
           func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, 
       successfully flag: Bool) {
    
               player.stop()
    
               print("Finish Playing")
    
           }
    
           func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, 
        error: Error?) {
    
                print(/error?.localizedDescription)
    
            }
    
        }