• iOS中音频的录制与播放(本地音频文件的播放)


    iOS功能开发涉及到音频处理时,最常见的时进行录音,以及音频文件的播放、停止播放等的操作。在开发中还要避免同一个音频文件,或不同音频文件之间的处理,比如说正在播放A音频时,可以停止播放A音频,也可以播放B音频时,停止播放A音频。在我的封装类中,已经对这方面做了处理。

    Demo下载地址

    音频开发注意事项

    1、录音功能主要使用到"AVAudioRecorder"类

    2、音频播放处理功能主要使用到"AVAudioPlayer"类

    3、通过NSTimer处理音量显示

    4、注意添加framework(AVFoundation.framework、AudioToolbox.framework)

    5、只可以用来播放本地音频文件,即使是网络音频也是先下载到本地,然后再进行播放

    1 主要代码

    [objc] view plain copy
     
    1. #import <Foundation/Foundation.h>  
    2.   
    3. @interface AudioRecorder : NSObject  
    4.   
    5. #pragma mark - 录音  
    6.   
    7. /// 实例化单例  
    8. + (AudioRecorder *)shareManager;  
    9.   
    10. #pragma mark - 音频处理-录音  
    11.   
    12. /// 开始录音  
    13. - (void)audioRecorderStartWithFilePath:(NSString *)filePath;  
    14.   
    15. /// 停止录音  
    16. - (void)audioRecorderStop;  
    17.   
    18. /// 录音时长  
    19. - (NSTimeInterval)durationAudioRecorderWithFilePath:(NSString *)filePath;  
    20.   
    21. #pragma mark - 音频处理-播放/停止  
    22.   
    23. /// 音频开始播放或停止  
    24. - (void)audioPlayWithFilePath:(NSString *)filePath;  
    25.   
    26. /// 音频播放停止  
    27. - (void)audioStop;  
    28.   
    29. @end  
        1. #import "AudioRecorder.h"  
        2.   
        3. // 导入录音头文件(注意添加framework:AVFoundation.framework、AudioToolbox.framework)  
        4. #import <AudioToolbox/AudioToolbox.h>  
        5. #import <AVFoundation/AVFoundation.h>  
        6. #import "AppDelegate.h"  
        7.   
        8. @interface AudioRecorder () <AVAudioRecorderDelegate>  
        9.   
        10. @property (nonatomic, strong) NSTimer *audioRecorderTimer;               // 录音音量计时器  
        11. @property (nonatomic, strong) NSMutableDictionary *audioRecorderSetting; // 录音设置  
        12. @property (nonatomic, strong) AVAudioRecorder *audioRecorder;            // 录音  
        13. @property (nonatomic, strong) AVAudioPlayer *audioPlayer;                // 播放  
        14. @property (nonatomic, assign) double audioRecorderTime;                  // 录音时长  
        15. @property (nonatomic, strong) UIView *imgView;                           // 录音音量图像父视图  
        16. @property (nonatomic, strong) UIImageView *audioRecorderVoiceImgView;    // 录音音量图像  
        17.   
        18. @end  
        19.   
        20. @implementation AudioRecorder  
        21.   
        22. #pragma mark - 实例化  
        23.   
        24. - (instancetype)init  
        25. {  
        26.     self = [super init];  
        27.       
        28.     if (self)  
        29.     {  
        30.         // 参数设置 格式、采样率、录音通道、线性采样位数、录音质量  
        31.         self.audioRecorderSetting = [NSMutableDictionary dictionary];  
        32.         [self.audioRecorderSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];  
        33.         [self.audioRecorderSetting setValue:[NSNumber numberWithInt:11025] forKey:AVSampleRateKey];  
        34.         [self.audioRecorderSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];  
        35.         [self.audioRecorderSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];  
        36.         [self.audioRecorderSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];  
        37.     }  
        38.       
        39.     return self;  
        40. }  
        41.   
        42. /// 录音单例  
        43. + (AudioRecorder *)shareManager  
        44. {  
        45.     static AudioRecorder *staticAudioRecorde;  
        46.     static dispatch_once_t once;  
        47.     dispatch_once(&once, ^{  
        48.         staticAudioRecorde = [[self alloc] init];  
        49.     });  
        50.       
        51.     return staticAudioRecorde;  
        52. }  
        53.   
        54. // 内存释放  
        55. - (void)dealloc  
        56. {  
        57.     // 内存释放前先停止录音,或音频播放  
        58.     [self audioStop];  
        59.     [self audioRecorderStop];  
        60.       
        61.     // 内存释放  
        62.     if (self.audioRecorderTime)  
        63.     {  
        64.         [self.audioRecorderTimer invalidate];  
        65.         self.audioRecorderTimer = nil;  
        66.     }  
        67.       
        68.     if (self.audioRecorderSetting)  
        69.     {  
        70.         self.audioRecorderSetting = nil;  
        71.     }  
        72.       
        73.     if (self.audioRecorder)  
        74.     {  
        75.         self.audioRecorder = nil;  
        76.     }  
        77.       
        78.     if (self.audioPlayer)  
        79.     {  
        80.         self.audioPlayer = nil;  
        81.     }  
        82.       
        83.     if (self.imgView)  
        84.     {  
        85.         self.imgView = nil;  
        86.     }  
        87.       
        88.     if (self.audioRecorderVoiceImgView)  
        89.     {  
        90.         self.audioRecorderVoiceImgView = nil;  
        91.     }  
        92. }  
        93.   
        94. #pragma mark - 音频处理-录音  
        95.   
        96. /// 开始录音  
        97. - (void)audioRecorderStartWithFilePath:(NSString *)filePath  
        98. {  
        99.     // 生成录音文件  
        100.     NSURL *urlAudioRecorder = [NSURL fileURLWithPath:filePath];  
        101.     self.audioRecorder = [[AVAudioRecorder alloc] initWithURL:urlAudioRecorder settings:self.audioRecorderSetting error:nil];  
        102.       
        103.     // 开启音量检测  
        104.     [self.audioRecorder setMeteringEnabled:YES];  
        105.     [self.audioRecorder setDelegate:self];  
        106.       
        107.     if (self.audioRecorder)  
        108.     {  
        109.         // 录音时设置audioSession属性,否则不兼容Ios7  
        110.         AVAudioSession *recordSession = [AVAudioSession sharedInstance];  
        111.         [recordSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];  
        112.         [recordSession setActive:YES error:nil];  
        113.           
        114.         if ([self.audioRecorder prepareToRecord])  
        115.         {  
        116.             [self.audioRecorder record];  
        117.               
        118.             //录音音量显示 75*111  
        119.             AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;  
        120.             UIView *view = [delegate window];  
        121.               
        122.             self.imgView = [[UIView alloc] initWithFrame:CGRectMake((view.frame.size.width - 120) / 2, (view.frame.size.height - 120) / 2, 120, 120)];  
        123.             [view addSubview:self.imgView];  
        124.             [self.imgView.layer setCornerRadius:10.0];  
        125.             [self.imgView.layer setBackgroundColor:[UIColor blackColor].CGColor];  
        126.             [self.imgView setAlpha:0.8];  
        127.               
        128.             self.audioRecorderVoiceImgView = [[UIImageView alloc] initWithFrame:CGRectMake((self.imgView.frame.size.width - 60) / 2, (self.imgView.frame.size.height - 660 * 111 / 75) / 2, 60, 660 * 111 / 75)];  
        129.             [self.imgView addSubview:self.audioRecorderVoiceImgView];  
        130.             [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_01.png"]];  
        131.             [self.audioRecorderVoiceImgView setBackgroundColor:[UIColor clearColor]];  
        132.   
        133.             // 设置定时检测  
        134.             self.audioRecorderTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(detectionVoice) userInfo:nil repeats:YES];  
        135.         }  
        136.     }  
        137. }  
        138.   
        139. /// 录音音量显示  
        140. - (void)detectionVoice  
        141. {  
        142.     // 刷新音量数据  
        143.     [self.audioRecorder updateMeters];  
        144.       
        145. //    // 获取音量的平均值  
        146. //    [self.audioRecorder averagePowerForChannel:0];  
        147. //    // 音量的最大值  
        148. //    [self.audioRecorder peakPowerForChannel:0];  
        149.       
        150.     double lowPassResults = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0]));  
        151.      
        152.     if (0 < lowPassResults <= 0.06)  
        153.     {  
        154.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_01.png"]];  
        155.     }  
        156.     else if (0.06 < lowPassResults <= 0.13)  
        157.     {  
        158.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_02.png"]];  
        159.     }  
        160.     else if (0.13 < lowPassResults <= 0.20)  
        161.     {  
        162.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_03.png"]];  
        163.     }  
        164.     else if (0.20 < lowPassResults <= 0.27)  
        165.     {  
        166.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_04.png"]];  
        167.     }  
        168.     else if (0.27 < lowPassResults <= 0.34)  
        169.     {  
        170.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_05.png"]];  
        171.     }  
        172.     else if (0.34 < lowPassResults <= 0.41)  
        173.     {  
        174.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_06.png"]];  
        175.     }  
        176.     else if (0.41 < lowPassResults <= 0.48)  
        177.     {  
        178.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_07.png"]];  
        179.     }  
        180.     else if (0.48 < lowPassResults <= 0.55)  
        181.     {  
        182.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_08.png"]];  
        183.     }  
        184.     else if (0.55 < lowPassResults <= 0.62)  
        185.     {  
        186.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_09.png"]];  
        187.     }  
        188.     else if (0.62 < lowPassResults <= 0.69)  
        189.     {  
        190.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_10.png"]];  
        191.     }  
        192.     else if (0.69 < lowPassResults <= 0.76)  
        193.     {  
        194.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_11.png"]];  
        195.     }  
        196.     else if (0.76 < lowPassResults <= 0.83)  
        197.     {  
        198.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_12.png"]];  
        199.     }  
        200.     else if (0.83 < lowPassResults <= 0.9)  
        201.     {  
        202.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_13.png"]];  
        203.     }  
        204.     else  
        205.     {  
        206.         [self.audioRecorderVoiceImgView setImage:[UIImage imageNamed:@"record_animate_14.png"]];  
        207.     }  
        208. }  
        209.   
        210. /// 停止录音  
        211. - (void)audioRecorderStop  
        212. {  
        213.     if (self.audioRecorder)  
        214.     {  
        215.         if ([self.audioRecorder isRecording])  
        216.         {  
        217.             // 获取录音时长  
        218.             self.audioRecorderTime = [self.audioRecorder currentTime];  
        219.             [self.audioRecorder stop];  
        220.          
        221.             // 停止录音后释放掉  
        222.             self.audioRecorder = nil;  
        223.         }  
        224.     }  
        225.       
        226.     // 移除音量图标  
        227.     if (self.audioRecorderVoiceImgView)  
        228.     {  
        229.         [self.audioRecorderVoiceImgView setHidden:YES];  
        230.         [self.audioRecorderVoiceImgView setImage:nil];  
        231.         [self.audioRecorderVoiceImgView removeFromSuperview];  
        232.         self.audioRecorderVoiceImgView = nil;  
        233.           
        234.         [self.imgView removeFromSuperview];  
        235.         self.imgView = nil;  
        236.     }  
        237.       
        238.     // 释放计时器  
        239.     [self.audioRecorderTimer invalidate];  
        240.     self.audioRecorderTimer = nil;  
        241. }  
        242.   
        243. /// 录音时长  
        244. - (NSTimeInterval)durationAudioRecorderWithFilePath:(NSString *)filePath  
        245. {  
        246.     NSURL *urlFile = [NSURL fileURLWithPath:filePath];  
        247.     self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFile error:nil];  
        248.     NSTimeInterval time = self.audioPlayer.duration;  
        249.     self.audioPlayer = nil;  
        250.     return time;  
        251. }  
        252.   
        253. #pragma mark - 音频处理-播放/停止  
        254.   
        255. /// 音频开始播放或停止  
        256. - (void)audioPlayWithFilePath:(NSString *)filePath  
        257. {  
        258.     if (self.audioPlayer)  
        259.     {  
        260.         // 判断当前与下一个是否相同  
        261.         // 相同时,点击时要么播放,要么停止  
        262.         // 不相同时,点击时停止播放当前的,开始播放下一个  
        263.         NSString *currentStr = [self.audioPlayer.url relativeString];  
        264.           
        265.         /* 
        266.         NSString *currentName = [self getFileNameAndType:currentStr]; 
        267.         NSString *nextName = [self getFileNameAndType:filePath]; 
        268.          
        269.         if ([currentName isEqualToString:nextName]) 
        270.         { 
        271.             if ([self.audioPlayer isPlaying]) 
        272.             { 
        273.                 [self.audioPlayer stop]; 
        274.                 self.audioPlayer = nil; 
        275.             } 
        276.             else 
        277.             { 
        278.                 self.audioPlayer = nil; 
        279.                 [self audioPlayerPlay:filePath]; 
        280.             } 
        281.         } 
        282.         else 
        283.         { 
        284.             [self audioPlayerStop]; 
        285.             [self audioPlayerPlay:filePath]; 
        286.         } 
        287.          */  
        288.           
        289.         // currentStr包含字符"file://location/",通过判断filePath是否为currentPath的子串,是则相同,否则不同  
        290.         NSRange range = [currentStr rangeOfString:filePath];  
        291.         if (range.location != NSNotFound)  
        292.         {  
        293.             if ([self.audioPlayer isPlaying])  
        294.             {  
        295.                 [self.audioPlayer stop];  
        296.                 self.audioPlayer = nil;  
        297.             }  
        298.             else  
        299.             {  
        300.                 self.audioPlayer = nil;  
        301.                 [self audioPlayerPlay:filePath];  
        302.             }  
        303.         }  
        304.         else  
        305.         {  
        306.             [self audioPlayerStop];  
        307.             [self audioPlayerPlay:filePath];  
        308.         }  
        309.     }  
        310.     else  
        311.     {  
        312.         [self audioPlayerPlay:filePath];  
        313.     }  
        314.       
        315. }  
        316.   
        317. /// 音频播放停止  
        318. - (void)audioStop  
        319. {  
        320.     [self audioPlayerStop];  
        321. }  
        322.   
        323.   
        324. /// 音频播放器开始播放  
        325. - (void)audioPlayerPlay:(NSString *)filePath  
        326. {  
        327.     // 判断将要播放文件是否存在  
        328.     BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];  
        329.     if (!isExist)  
        330.     {  
        331.         return;  
        332.     }  
        333.       
        334.     NSURL *urlFile = [NSURL fileURLWithPath:filePath];  
        335.     self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFile error:nil];  
        336.     if (self.audioPlayer)  
        337.     {  
        338.         if ([self.audioPlayer prepareToPlay])  
        339.         {  
        340.             // 播放时,设置喇叭播放否则音量很小  
        341.             AVAudioSession *playSession = [AVAudioSession sharedInstance];  
        342.             [playSession setCategory:AVAudioSessionCategoryPlayback error:nil];  
        343.             [playSession setActive:YES error:nil];  
        344.               
        345.             [self.audioPlayer play];  
        346.         }  
        347.     }  
        348. }  
        349.   
        350. /// 音频播放器停止播放  
        351. - (void)audioPlayerStop  
        352. {  
        353.     if (self.audioPlayer)  
        354.     {  
        355.         if ([self.audioPlayer isPlaying])  
        356.         {  
        357.             [self.audioPlayer stop];  
        358.         }  
        359.           
        360.         self.audioPlayer = nil;  
        361.     }  
        362. }  
        363.   
        364. @end

        365. [objc] view plain copy
           
            1. 引入封装类头文件  
            2. #import "AudioRecorder.h"  
            3.   
            4. // 开始录音  
            5. - (void)startRecorder  
            6. {  
            7.     self.filePath = GetFilePathWithDate();  
            8.     [[AudioRecorder shareManager] audioRecorderStartWithFilePath:self.filePath];  
            9. }  
            10.   
            11. // 停止录音,并保存  
            12. - (void)saveRecorder  
            13. {  
            14.     [[AudioRecorder shareManager] audioRecorderStop];  
            15. }  
            16.   
            17. // 录音开始播放,或停止  
            18. - (void)playRecorder  
            19. {  
            20.     [[AudioRecorder shareManager] audioPlayWithFilePath:self.filePath];  
            21. }  
            22.   
            23. // 录音停止播放  
            24. - (void)stopRecorder  
            25. {  
            26.     [[AudioRecorder shareManager] audioStop];  
            27. }  
  • 相关阅读:
    [linux] ARCH LINUX 常见问题及实用工具汇总
    [TLSR8267] 泰凌微 telink tlsr8267 ble ADC 用法浅谈
    [小黑科技] 破解一个电控升降桌,并改造成语音控制(上)—— 模拟中间人与控制手柄交互
    [蓝牙前沿应用] 照明即平台 —— 通过蓝牙增强服务提高照明投资回报率(蓝牙MESH、定位AoA、AoD)
    [Node.js] 3、搭建hexo博客
    [IOT] 自制蓝牙工牌办公室定位系统 (二)—— 基于ESP32的蓝牙信号扫描系统
    [IOT] 自制蓝牙工牌办公室定位系统 (一)—— 阿里物联网平台概览及打通端到云(硬核&#183;干货)
    [python] PyMouse、PyKeyboard用python操作鼠标和键盘
    [python] bluepy 一款python封装的BLE利器
    [安卓] 20、基于蓝牙BLE的广播包高频快速搜索
  • 原文地址:https://www.cnblogs.com/edensyd/p/8483972.html
Copyright © 2020-2023  润新知