0、錄音前很重要的一步, 創建音頻會話者
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch {
print(error)
}
在整個錄音或播放音頻的過程中只需要初始化一次就好
其中setCategory的值決定這個會話者的功能
音頻會話分類
分類 | 作用 | 是否允許跟其他應用混音 | 支持音頻輸入 | 支持音頻輸出 |
---|---|---|---|---|
AVAudioSessionCategoryAmbient | 一般app應用 | ?? | ?? | |
...SoloAmbient (默認) | 一般app應用 | ?? | ||
...Playback | 音頻播放器 | 可選 | ?? | |
...Record | 錄音機,音頻捕捉 | ?? | ||
...PlayAndRecord | VoIp,語音聊天 | 可選 | ?? | ?? |
...AudioProcessing | 離線會話和處理(僅需要用到編解碼處理功能的) | |||
...MultiRoute | 使用外設硬件的應用 | ?? | ?? |
其中一些分類可以使用option和modes進行進一步配置.
我們來看看AVAudioRecorder的API
1、初始化一個AVAudioRecorder對象
蘋果提供了兩個初始化方法
第一個初始化方法:
傳入保存這個錄音文件的URL路徑, setting這個參數是個字典, 里面是一個音頻設置信息,字典相對應的key, 可以去參考 AVAudioSettings.h ,值都是NSNumber類型
public init(url: URL, settings: [String : Any]) throws
```
第一個初始化AVAudioRecorder方法中的setting字典一般設置的內容, 可以參考相關術語概念[iOS 音頻學習基本術語和概念](http://www.lxweimin.com/p/3802d2c6f051)
`AVSampleRateKey: String` 采樣率 8000, 44100等
`AVNumberOfChannelsKey: String` 聲道數 1為單聲道, 2為雙聲道(立體聲)
`AVLinearPCMBitDepthKey: String` 位寬 數據一般為: 8, 16, 24, 32
`AVEncoderAudioQualityKey: String` 錄音質量,在`AVAudioQuality`枚舉中,值有`min low medium high max`四個
`AVLinearPCMIsBigEndianKey: String` 大小端編碼:1為大端, 0為小端. 如果你不懂什么是大小端可以看[iOS 關于大小端以及一些數據補位](http://www.lxweimin.com/p/79f349409cbf)
` AVFormatIDKey: String` 錄音數據格式 可以參考CoreAudio 里面相關的值
其中 `AVFormatIDKey`的值有
public var kAudioFormatLinearPCM: AudioFormatID { get }
public var kAudioFormatAC3: AudioFormatID { get }
public var kAudioFormat60958AC3: AudioFormatID { get }
public var kAudioFormatAppleIMA4: AudioFormatID { get }
public var kAudioFormatMPEG4AAC: AudioFormatID { get }
public var kAudioFormatMPEG4CELP: AudioFormatID { get }
public var kAudioFormatMPEG4HVXC: AudioFormatID { get }
public var kAudioFormatMPEG4TwinVQ: AudioFormatID { get }
public var kAudioFormatMACE3: AudioFormatID { get }
public var kAudioFormatMACE6: AudioFormatID { get }
public var kAudioFormatULaw: AudioFormatID { get }
public var kAudioFormatALaw: AudioFormatID { get }
public var kAudioFormatQDesign: AudioFormatID { get }
public var kAudioFormatQDesign2: AudioFormatID { get }
public var kAudioFormatQUALCOMM: AudioFormatID { get }
public var kAudioFormatMPEGLayer1: AudioFormatID { get }
public var kAudioFormatMPEGLayer2: AudioFormatID { get }
public var kAudioFormatMPEGLayer3: AudioFormatID { get }
public var kAudioFormatTimeCode: AudioFormatID { get }
public var kAudioFormatMIDIStream: AudioFormatID { get }
public var kAudioFormatParameterValueStream: AudioFormatID { get }
public var kAudioFormatAppleLossless: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_HE: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_LD: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_ELD: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_ELD_SBR: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_ELD_V2: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_HE_V2: AudioFormatID { get }
public var kAudioFormatMPEG4AAC_Spatial: AudioFormatID { get }
public var kAudioFormatAMR: AudioFormatID { get }
public var kAudioFormatAMR_WB: AudioFormatID { get }
public var kAudioFormatAudible: AudioFormatID { get }
public var kAudioFormatiLBC: AudioFormatID { get }
public var kAudioFormatDVIIntelIMA: AudioFormatID { get }
public var kAudioFormatMicrosoftGSM: AudioFormatID { get }
public var kAudioFormatAES3: AudioFormatID { get }
public var kAudioFormatEnhancedAC3: AudioFormatID { get }
setting字典的代碼:
////定義音頻的編碼參數,這部分比較重要,決定錄制音頻文件的格式、音質、容量大小等
let recordSettings = [AVSampleRateKey : NSNumber(value: Float(44100.0) as Float),//聲音采樣率
AVFormatIDKey : NSNumber(value: Int32(kAudioFormatMPEG4AAC) as Int32),//編碼格式
AVNumberOfChannelsKey : NSNumber(value: 1 as Int32),//采集音軌
AVEncoderAudioQualityKey : NSNumber(value: Int32(AVAudioQuality.medium.rawValue) as Int32)]//音頻質量
初始化代碼:
do {
try audioRecorder = AVAudioRecorder(url: self.directoryURL()!,
settings: recordSettings)//初始化實例
audioRecorder.prepareToRecord()//準備錄音
} catch {
print(error)
}
//錄音保存路徑
func directoryURL() -> URL? {
//定義并構建一個url來保存音頻,音頻文件名為ddMMyyyyHHmmss.caf
//根據時間來設置存儲文件名
let currentDateTime = Date()
let formatter = DateFormatter()
formatter.dateFormat = "ddMMyyyyHHmmss"
let recordingName = formatter.string(from: currentDateTime)+".caf"
print(recordingName)
let fileManager = FileManager.default
let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = urls[0] as URL
let soundURL = documentDirectory.appendingPathComponent(recordingName)
return soundURL
}
>第二個初始化方法
傳入保存這個錄音文件的URL路徑, 還有AVAudioFormat
@available(iOS 10.0, *)
public init(url: URL, format: AVAudioFormat) throws
`AVAudioFormat`其實就是包裝了一下`Core Audio`框架中的`AudioStreamBasicDescription(asbd)`這個結構體,所以`AVAudioFormat`的初始化基本都要的參數都要傳入`AudioStreamBasicDescription `的值
那么`AudioStreamBasicDescription`是什么呢, 簡單理解就是描述音頻的基本格式信息, 跟第一個初始化AVAudioRecorder方法中的setting差不多, 只是更詳細
public struct AudioStreamBasicDescription {
public var mSampleRate: Float64 采樣率
public var mFormatID: AudioFormatID 數據格式
public var mFormatFlags: AudioFormatFlags 數據格式的標志, 這個不知道干嘛的, 還沒理解,linear PCM一般傳kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked
public var mBytesPerPacket: UInt32 多少個字節每包
public var mFramesPerPacket: UInt32 多少幀每包
public var mBytesPerFrame: UInt32 多少個字節每一幀
public var mChannelsPerFrame: UInt32 聲音通道數
public var mBitsPerChannel: UInt32 位寬 每個聲音通道的位寬
public var mReserved: UInt32 預留屬性
}
我們再看看提供的方法, 用起來還是比較簡單的, 所以備注一下就好了
open func prepareToRecord() -> Bool 準備錄音, 這個在錄音之前要調用一下, 底層可能會給你做一些事
open func record() -> Bool 錄音
@available(iOS 6.0, *)
open func record(atTime time: TimeInterval) -> Bool 在未來的某個時刻開始錄音
open func record(forDuration duration: TimeInterval) -> Bool 錄音, 控制時長
@available(iOS 6.0, *)
open func record(atTime time: TimeInterval, forDuration duration: TimeInterval) -> Bool 在未來的某段時間錄多少時間的音頻
open func pause() 暫停
open func stop() 停止
open func deleteRecording() -> Bool 刪除錄音
下面是屬性
open var isRecording: Bool { get } 是否正在錄音
open var url: URL { get } 錄音存放的url
open var settings: [String : Any] { get } 錄音格式配置字典
@available(iOS 10.0, *)
open var format: AVAudioFormat { get } 錄音格式配置
unowned(unsafe) open var delegate: AVAudioRecorderDelegate? 代理
open var currentTime: TimeInterval { get } 當前錄音的時長
@available(iOS 6.0, *)
open var deviceCurrentTime: TimeInterval { get } 設備當前時間
open func updateMeters() 更新音量等數據
open func peakPower(forChannel channelNumber: Int) -> Float 最高音量
open func averagePower(forChannel channelNumber: Int) -> Float 平均音量
@available(iOS 7.0, *)
open var channelAssignments: [AVAudioSessionChannelDescription]? 每個聲音通道描述數組
錄音操作代碼:
@IBAction func startRecord(_ sender: AnyObject) {
//開始錄音
if !audioRecorder.isRecording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
audioRecorder.record()
print("record!")
} catch {
}
}
}
@IBAction func stopRecord(_ sender: AnyObject) {
//停止錄音
audioRecorder.stop()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
print("stop!!")
} catch {
}
}
下面是錄音器的代理
public protocol AVAudioRecorderDelegate : NSObjectProtocol {
@available(iOS 3.0, *)
optional public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) 錄音成功的回調
@available(iOS 3.0, *)
optional public func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) 錄音發生錯誤的的回調
@available(iOS, introduced: 2.2, deprecated: 8.0)
optional public func audioRecorderBeginInterruption(_ recorder: AVAudioRecorder) 錄音開始中斷的回調
@available(iOS, introduced: 6.0, deprecated: 8.0)
optional public func audioRecorderEndInterruption(_ recorder: AVAudioRecorder, withOptions flags: Int) 錄音結束中斷的回調
###錄音播放AVAudioPlayer
里面的屬性和方法跟AVAudioRecorder差不多, 所以就不多說了, 附上簡單的代碼
@IBAction func startPlaying(_ sender: AnyObject) {
//開始播放
if (!audioRecorder.isRecording){
do {
try audioPlayer = AVAudioPlayer(contentsOf: audioRecorder.url)
audioPlayer.play()
print("play!!")
} catch {
}
}
}
@IBAction func pausePlaying(_ sender: AnyObject) {
//暫停播放
if (!audioRecorder.isRecording){
do {
try audioPlayer = AVAudioPlayer(contentsOf: audioRecorder.url)
audioPlayer.pause()
print("pause!!")
} catch {
}
}
}