swift 录音 AVAudioRecorder

距离上次写博客已经好久好久了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
        /******
         采样率越高,文件越大,质量越好,反之,文件小,质量相对差一些,但是低于普通的音频,人耳并不能明显的分辨出好坏。最终选取哪一种采样率,由我们的耳朵来判断。建议使用标准的采样率,8000、16000、22050、44100。
         *****/
        recordSetting[AVSampleRateKey] = NSNumber(value: 8000)
        //The quality of record
        recordSetting[AVEncoderAudioQualityKey] = NSNumber(value: AVAudioQuality.high.rawValue)
        //线性采样位数  8、16、24、32
        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,然后声音特别细)


就这些了 好像有点乱。。。。睡觉




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值