2018年05月16日 15:22:44 msmwncx阅读数:548

https://blog.csdn.net/msmwncx/article/details/80336973

版权声明:本文为博主原创文章,未经博主允许不得转载。如有问题,请联系QQ547394765 https://blog.csdn.net/msmwncx/article/details/80336973

距离上次写博客已经好久好久了ZZZzzzzzzz。

首先交代下用处,做的IM项目,需要语音聊天,研究了下AVAudioRecorder。

其实挺简单的,主要步骤就是 创建一个recorder -> recorder.record() -> recorder.stop()

不多说 上代码

func createRecord(path: String) {

if self.recorder != nil {

self.resetRecorder()

}

let url = URL(fileURLWithPath: path)

self.cafPathStr = path

self.mp3PathStr = self.recordFileCaf2Mp3(cafPath: path)

let setting = self.recordSetting()

do {

self.recorder = try AVAudioRecorder(url: url, settings: setting)

self.recorder?.delegate = self

self.recorder?.isMeteringEnabled = true

} catch {

XMPPAudioLog("create recorder error:")

}

}

func startRecord(path: String) {

guard self.recorder == nil else {

EdoAssertionFailure("should reset recorder before start record")

return

}

if self.recorder == nil {

self.createRecord(path: path)

}

guard let _ = self.recorder else {

assertionFailure("ChatAudio: recorder could not be nil")

return

}

//if isRecording, should stop first

if let _ = self.recorder?.isRecording {

self.recorder?.stop()

}

//stop all player

self.stopAllMusic()

let audioSession = AVAudioSession.sharedInstance()

do {

try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)

if let isRecorder = self.recorder?.isRecording, isRecorder == false {

self.recorder?.record()

}

} catch {

}

}

这里的mp3PathStr是转换成MP3格式的路径

这里是一些配置还有大小以及mp3路径的转换方法

func recordSetting() -> [String: Any] {

var recordSetting = [String: Any]()

//format of record

/****

         kAudioFormatMPEG4AAC压缩格式能在显著减小文件的同时,保证音频的质量。

         ****/

recordSetting[AVFormatIDKey] = NSNumber(value: kAudioFormatLinearPCM)

//sampling rate of record

/******

         采样率越高,文件越大,质量越好,反之,文件小,质量相对差一些,但是低于普通的音频,人耳并不能明显的分辨出好坏。最终选取哪一种采样率,由我们的耳朵来判断。建议使用标准的采样率,8000160002205044100

         *****/

recordSetting[AVSampleRateKey] = NSNumber(value: 8000)

//The quality of record

recordSetting[AVEncoderAudioQualityKey] = NSNumber(value: AVAudioQuality.high.rawValue)

//线性采样位数  8162432

recordSetting[AVLinearPCMBitDepthKey] = NSNumber(value: 8)

//录音通道数  1 2

/****

         AVNumberOfChannelsKey用于指定记录音频的通道数。1为单声道,2为立体声。

         ***/

recordSetting[AVNumberOfChannelsKey] = NSNumber(value: 2)

return recordSetting

}

func fileSizeAtPath(path: String) -> String {

if FileManager.default.fileExists(atPath: path) {

let attributes = try? FileManager.default.attributesOfItem(atPath: path)

if let attrs = attributes, let size = attrs[FileAttributeKey(rawValue:"NSFileSize")] as? Int64 {

return ByteCountFormatter.string(fromByteCount: size, countStyle: ByteCountFormatter.CountStyle.file)

}

}

return "0 KB"

}

func recordFileCaf2Mp3(cafPath: String) -> String {

var mp3Path = cafPath

if cafPath.hasSuffix(".caf") {

mp3Path = cafPath.replacingOccurrences(of: "caf", with: "mp3", options: NSString.CompareOptions.caseInsensitive, range: Range(cafPath.index(cafPath.startIndex, offsetBy: cafPath.count - 3)..<cafPath.endIndex))

}

return mp3Path

}

由于我这边是要做语音聊天,所以每次结束都会把recorder销毁掉

func deleteRecording() {

guard let recorder = self.recorder, recorder.isRecording == false else {

assertionFailure("ChatAudio: recorder must be stopped")

return

}

self.recorder?.deleteRecording()

self.resetRecorder()

}

func resetRecorder() {

self.recorder?.stop()

self.recorder = nil

self.mp3PathStr = ""

self.cafPathStr = ""

}

emmmm 好像就这么多了  具体一些缘由 为什么这么写什么的 可以参考一下apple的官方资料

然后就是转MP3

转mp3我是用的lame.h 和 libmp3lame.a 然后遇到一个什么 libmp3lame.a 不支持bitcode什么的问题 于是用以下解决

1.http://sourceforge.net/projects/lame/files/lame/3.99/ 下载lame的最新版本并解压

2.https://github.com/kewlbear/lame-ios-build   下载build的脚本 下载之后得到lame-build.sh拷贝到刚才解压后的文件夹

3.用一些编辑器按照注释修改lame-build.sh 如下图

4.cd 到1解压的目录下 执行脚本 chmod 777 lame-build.sh 等待1分钟左右就编译完成了

5.里边生成fat-lame目录和thin-lame目录,分别存放合并所有指令集的静态库,以及各指令集的静态库. 具体用哪个里边的lame.h和libmp3lame.a 我就忘记了。。。试一下吧。

然后就是转MP3文件了

我查了下资料,前人大部分都是用的OC写的 于是我用了一个OC文件转译了一下

+ (BOOL)audio_PCMtoMP3:(NSString *)cafPath mp3Path:(NSString *)mp3Path {

@try {

int read, write;

FILE *pcm = fopen([cafPath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置

fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header

FILE *mp3 = fopen([mp3Path cStringUsingEncoding:1], "wb");  //output 输出生成的Mp3文件位置

const int PCM_SIZE = 8192;

const int MP3_SIZE = 8192;

short int pcm_buffer[PCM_SIZE*2];

unsigned char mp3_buffer[MP3_SIZE];

lame_t lame = lame_init();

//should be equle with AVSampleRateKey

lame_set_in_samplerate(lame, 8000.0);

lame_set_VBR(lame, vbr_default);

lame_init_params(lame);

do {

read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);

if (read == 0)

write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);

else

write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

fwrite(mp3_buffer, write, 1, mp3);

} while (read != 0);

lame_close(lame);

fclose(mp3);

fclose(pcm);

}

@catch (NSException *exception) {

NSLog(@"%@",[exception description]);

return NO;

}

@finally {

NSLog(@"MP3生成成功: %@",mp3Path);

return YES;

}

}

注意里边有一句

lame_set_in_samplerate(lame, 8000.0);

这里的8000要与recorder设置里的采样率一致,否则会变声。(我感觉一些app的变音就是这么来的,有兴趣可以试试,开始我设置的采样率是8000,这里写的是44100,然后声音特别细)

swift 录音 AVAudioRecorder的更多相关文章

  1. iOS开发简记(4):录音AVAudioRecorder

    录音,声音的采集,一般有两种实现办法,一是使用AVAudioRecorder,一是使用AudioUnit.如果只是简单的录音,使用AVAudioRecorder就可以了,如果想更灵活地处理刚录到的声音 ...

  2. iOS开发(4):录音AVAudioRecorder

    录音,声音的采集,一般有两种实现办法,一是使用AVAudioRecorder,一是使用AudioUnit.如果只是简单的录音,使用AVAudioRecorder就可以了,如果想更灵活地处理刚录到的声音 ...

  3. Domain=NSOSStatusErrorDomain Code=1937337955 关于iOS录音AVAudioRecorder与音频播放AVAudioPlayer真机调试录音不能播放的问题

    error:Domain=NSOSStatusErrorDomain Code=1937337955 ,这个错误很常见, 原因是因为我们需要调用另外一个AVAudioPlayer 的初始化方法,来确定 ...

  4. ios录音Demo

    <AudioToolbox/AudioToolbox.h> :这个库是C的接口,偏向于底层,主要用于在线流媒体的播放 <AVFoundation/AVFoundation.h> ...

  5. Audio/Movie/Image

    Audio 1. 引入AVFoundation 库,此库用于处理音频的播放. > 使用AVAudioPlayer 播放音频,此类只能播放本地音频文件.对于流媒体(边下边播)的播放使用第三方框架实 ...

  6. 用swift实现自动录音器

    基本介绍 自动录音与一般录音区别在:不用像微信那样按下录音-松手结束,而是根据说话声音的大小自动判断该录音和该停止的点,然后可以做到结束录音之后马上播放出来.类似于达到会说话的汤姆猫那样的效果. 在自 ...

  7. Swift实现iOS录音与播放音频功能

    作用AVPLayer:可以用来播放在线及本地音视频AVAudioSession:音频会话,主要用来管理音频设置与硬件交互使用时需要导入 #import <AVFoundation/AVFound ...

  8. iOS AVAudioRecorder 录音频率、声道、位数配置 wav格式

    iOS AVAudioRecorder 录音频率.声道.位数配置 #pragma mark 录音设置 - (void)setUP_VOICE_RECOARDER { NSError *error = ...

  9. iOS开发-解决AVAudioRecorder录音文件无法保存的问题

    我们在开发iOS客户端APP时,有时候会用到录音的功能,一般会使 AVAudioRecorder 这个类.如下面这样: @interface MyViewController : UIViewCont ...

随机推荐

  1. Eclipse启动选择启动空间

    window -->preferences-->General-->Startup and Shutdown -->Workspaces-->勾选Prompt for w ...

  2. 视频编解码 基本概念:GOP

    前言 产品开发要求添加视频剪辑功能,翻阅有关的文档,查到了GOP(group of pictures)这个概念. 解析 GOP说白了就是两个I帧之间的间隔.比较说GOP为120,如果是720p60的话 ...

  3. CodeForces - 862C Mahmoud and Ehab and the xor(构造)

    题意:要求构造一个n个数的序列,要求n个数互不相同,且异或结果为x. 分析: 1.因为0 ^ 1 ^ 2 ^ 3 ^ ... ^ (n - 3) ^ (n - 2) ^ (0 ^ 1 ^ 2 ^ 3 ...

  4. synchronized和锁(ReentrantLock) 区别

    synchronized和锁(ReentrantLock) 区别 java的两种同步方式, Synchronized与ReentrantLock的区别 并发(一):理解可重入锁 可重入锁和不可重入锁 ...

  5. Linux动静态库

    gcc编译过程 预处理,gcc -E,.c->.i 展开宏和头文件,替换条件编译,删除注释.空白和空行 编译, gcc -S,.i -> .s 检查语法规范 [消耗时间和系统资源最多] 汇 ...

  6. 033.SAP上查看IDOC接口,PI接口查不到的日志记录,可能在IDOC接口日志里面

    01. SAP系统发料之后,数据没有传输到条码系统,同事也没有任何bc01的日志,这是就要考虑是不是在IDOC接口了,输入事务代码WE02或者WE05 02.双击查看内容 03.点开就能看到详细内容了 ...

  7. eshop-环境配置

    1. iptables # Generated by iptables-save v1. :: #*filter #:INPUT ACCEPT [:] #:FORWARD ACCEPT [:] #:O ...

  8. Codeforces Forethought Future Cup Elimination Round 选做

    1146C Tree Diameter 题意 交互题.有一棵 \(n(n\le 100)\) 个点的树,你可以进行不超过 \(9\) 次询问,每次询问两个点集中两个不在同一点集的点的最大距离.求树的直 ...

  9. 前端性能优化----reflow(回流)和repaint(重绘)

    什么是reflow和repaint(原文链接:http://www.cnblogs.com/Peng2014/p/4687218.html) reflow:例如某个子元素样式发生改变,直接影响到了其父 ...

  10. Numpy使用大全(python矩阵相关运算大全)-Python数据分析基础2

    //2019.07.10python数据分析基础——numpy(数据结构基础) import numpy as np: 1.python数据分析主要的功能实现模块包含以下六个方面:(1)numpy—— ...