Last active
June 2, 2023 08:21
-
-
Save AshvinGudaliya/e8d18281e16cbe75971581c188e308dd to your computer and use it in GitHub Desktop.
Simple Audio recorder and player in swift 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AGAudioRecorder.swift | |
// BaseProject | |
// | |
// Created by AshvinGudaliya on 17/09/18. | |
// Copyright © 2018 AshvinGudaliya. All rights reserved. | |
// | |
import UIKit | |
import AVFoundation | |
enum AGAudioRecorderState { | |
case Pause | |
case Play | |
case Finish | |
case Failed(String) | |
case Recording | |
case Ready | |
case error(Error) | |
} | |
protocol AGAudioRecorderDelegate { | |
func agAudioRecorder(_ recorder: AGAudioRecorder, withStates state: AGAudioRecorderState) | |
func agAudioRecorder(_ recorder: AGAudioRecorder, currentTime timeInterval: TimeInterval, formattedString: String) | |
} | |
class AGAudioRecorder: NSObject { | |
private var isAudioRecordingGranted: Bool = false | |
private var filename: String = "" | |
private var recorderState: AGAudioRecorderState = .Ready { | |
willSet{ | |
delegate?.agAudioRecorder(self, withStates: newValue) | |
} | |
} | |
private var audioRecorder: AVAudioRecorder! = nil | |
private var audioPlayer: AVAudioPlayer! = nil | |
private var meterTimer: Timer! = nil | |
private var currentTimeInterval: TimeInterval = 0.0 | |
var delegate: AGAudioRecorderDelegate? | |
init(withFileName filename: String) { | |
super.init() | |
self.recorderState = .Ready | |
self.filename = filename | |
self.check_record_permission() | |
} | |
private func check_record_permission() { | |
switch AVAudioSession.sharedInstance().recordPermission() { | |
case .granted: | |
isAudioRecordingGranted = true | |
break | |
case .denied: | |
isAudioRecordingGranted = false | |
break | |
case .undetermined: | |
AVAudioSession.sharedInstance().requestRecordPermission({ (allowed) in | |
if allowed { | |
self.isAudioRecordingGranted = true | |
} else { | |
self.isAudioRecordingGranted = false | |
} | |
}) | |
break | |
} | |
} | |
private func documentsDirectory() -> URL { | |
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) | |
let documentsDirectory = paths[0] | |
return documentsDirectory | |
} | |
func fileUrl() -> URL { | |
let filename = "\(self.filename).m4a" | |
let filePath = documentsDirectory().appendingPathComponent(filename) | |
return filePath | |
} | |
func changeFile(withFileName filename: String) { | |
self.filename = filename | |
if audioPlayer != nil { | |
doPause() | |
} | |
if audioRecorder != nil { | |
doStopRecording() | |
setupRecorder() | |
} | |
} | |
private func setupRecorder() { | |
if isAudioRecordingGranted { | |
let session = AVAudioSession.sharedInstance() | |
do { | |
try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) | |
try session.setActive(true) | |
let settings = [ | |
AVFormatIDKey: Int(kAudioFormatMPEG4AAC), | |
AVSampleRateKey: 44100, | |
AVNumberOfChannelsKey: 2, | |
AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue | |
] | |
audioRecorder = try AVAudioRecorder(url: fileUrl(), settings: settings) | |
audioRecorder.delegate = self | |
audioRecorder.isMeteringEnabled = true | |
audioRecorder.prepareToRecord() | |
self.recorderState = .Ready | |
} | |
catch let error { | |
recorderState = .error(error) | |
} | |
} | |
else { | |
recorderState = .Failed("Don't have access to use your microphone.") | |
} | |
} | |
@objc private func updateAudioMeter(timer: Timer) { | |
if audioRecorder.isRecording { | |
currentTimeInterval = currentTimeInterval + 0.01 | |
let hr = Int((currentTimeInterval / 60) / 60) | |
let min = Int(currentTimeInterval / 60) | |
let sec = Int(currentTimeInterval.truncatingRemainder(dividingBy: 60)) | |
let totalTimeString = String(format: "%02d:%02d:%02d", hr, min, sec) | |
delegate?.agAudioRecorder(self, currentTime: currentTimeInterval, formattedString: totalTimeString) | |
audioRecorder.updateMeters() | |
} | |
} | |
private func finishAudioRecording(success: Bool) { | |
if success { | |
audioRecorder?.stop() | |
meterTimer?.invalidate() | |
recorderState = .Finish | |
} | |
else { | |
recorderState = .Failed("Recording failed.") | |
} | |
} | |
private func preparePlay() { | |
do { | |
audioPlayer = try AVAudioPlayer(contentsOf: fileUrl()) | |
audioPlayer.delegate = self | |
audioPlayer.prepareToPlay() | |
recorderState = .Ready | |
} | |
catch { | |
recorderState = .error(error) | |
debugPrint(error) | |
} | |
} | |
func doRecord() { | |
if audioRecorder == nil { | |
setupRecorder() | |
} | |
if audioRecorder.isRecording { | |
doStopRecording() | |
} | |
else { | |
audioRecorder.record() | |
currentTimeInterval = 0.0 | |
meterTimer = Timer.scheduledTimer(timeInterval: 0.01, target:self, selector:#selector(self.updateAudioMeter(timer:)), userInfo:nil, repeats:true) | |
recorderState = .Recording | |
} | |
} | |
func doStopRecording() { | |
guard audioRecorder != nil else { | |
return | |
} | |
audioRecorder.stop() | |
let audioSession = AVAudioSession.sharedInstance() | |
do { | |
try audioSession.setActive(false) | |
finishAudioRecording(success: true) | |
} catch { | |
recorderState = .error(error) | |
} | |
} | |
func doPlay() { | |
if audioPlayer == nil { | |
self.preparePlay() | |
} | |
if audioRecorder != nil, audioRecorder.isRecording { | |
self.doStopRecording() | |
} | |
if audioPlayer.isPlaying { | |
doPause() | |
} | |
else{ | |
if FileManager.default.fileExists(atPath: fileUrl().path) { | |
preparePlay() | |
audioPlayer.play() | |
recorderState = .Play | |
} | |
else { | |
recorderState = .Failed("Audio file is missing.") | |
} | |
} | |
} | |
func doPause() { | |
guard audioPlayer != nil else { | |
return | |
} | |
if audioRecorder != nil, audioRecorder.isRecording { | |
self.doStopRecording() | |
} | |
if (audioPlayer.isPlaying){ | |
audioPlayer.pause() | |
} | |
recorderState = .Pause | |
} | |
} | |
extension AGAudioRecorder: AVAudioRecorderDelegate, AVAudioPlayerDelegate { | |
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { | |
if !flag { | |
finishAudioRecording(success: false) | |
} | |
} | |
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { | |
} | |
} |
pause not working
Hi, I want to get Decibel values for audio.
And i want to create Sound pressure level meter from it which goes up-to 120 and give me accurate decibel values as we get on Decibel analogue meters.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to Use?
Answer:
New code on Repositories