• iOS语音


    [objc] view plain copy
    1. <span style="white-space:pre">    </span>语音技术近来可是出遍了风头,从iphone4s的siri,到微信的语音聊天等等,极大地方便了人们的社交生活,也体现了当今移动科技发展的迅猛。当然,作为一位移动开发的从业人员怎能落伍呢!今天我们就来简单的实现一下语音聊天的功能。  
    [objc] view plain copy
    1. <span style="white-space:pre">    </span>这次Demo使用的是Speex对录制的声音进行语音压缩,并且进行ogg的封装。由于本人水平有限,尝试了几次对ogg库的编译都不成功,于是终于在Code4App上找到了一个Demo,把它的speex和封装好的ogg拿了过来,如果大家对ios支持的语音格式不太了解的话可以看一下这篇文章:http://www.csdn.net/article/2012-03-16/313194  

    首先上图,聊天界面:

    源码如下:

    聊天界面头文件:

    [objc] view plain copy
    1. #import <UIKit/UIKit.h>  
    2. #import "RecorderManager.h"  
    3. #import "PlayerManager.h"  
    4.   
    5. @interface MainViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, RecordingDelegate, PlayingDelegate, UIGestureRecognizerDelegate>  
    6.   
    7. - (IBAction)talk:(id)sender;  
    8.   
    9. @property (strong, nonatomic) IBOutlet UITableView *vTableView;  
    10.   
    11. @property (strong, nonatomic) IBOutlet UIButton *speekBtb;  
    12.   
    13. @property (assign) BOOL isSpeak;  
    14.   
    15. @property (strong, nonatomic) NSMutableArray *voiceArray;  
    16.   
    17. @property (strong, nonatomic) NSString *fileName;  
    18.   
    19. @property (assign) BOOL isPlaying;  
    20.   
    21. @end  

    实现:

    [objc] view plain copy
    1. #import "MainViewController.h"  
    2.   
    3. @interface MainViewController()  
    4.   
    5. @end  
    6.   
    7. @implementation MainViewController  
    8. @synthesize isSpeak = _isSpeak;  
    9. @synthesize voiceArray = _voiceArray;  
    10. @synthesize fileName = _fileName;  
    11. @synthesize isPlaying = _isPlaying;  
    12.   
    13. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
    14. {  
    15.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
    16.     if (self) {  
    17.         // Custom initialization  
    18.     }  
    19.     return self;  
    20. }  
    21.   
    22. - (void)viewDidLoad  
    23. {  
    24.     [super viewDidLoad];  
    25.     // Do any additional setup after loading the view from its nib.  
    26.       
    27.     self.vTableView.delegate = self;  
    28.     self.voiceArray = [[NSMutableArray alloc] init];  
    29.       
    30.     UILongPressGestureRecognizer *guesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handSpeakBtnPressed:)];  
    31.     guesture.delegate = self;  
    32.     guesture.minimumPressDuration = 0.01f;  
    33.       
    34.     //录音按钮添加手势操作  
    35.     [_speekBtb addGestureRecognizer:guesture];  
    36. }  
    37.   
    38. - (void)didReceiveMemoryWarning  
    39. {  
    40.     [super didReceiveMemoryWarning];  
    41.     // Dispose of any resources that can be recreated.  
    42. }  
    43.   
    44. #pragma mark tableView+++++++++++++++++++++++++++++++++++++++  
    45. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{  
    46.     return 1;  
    47. }  
    48.   
    49. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{  
    50.     UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];  
    51.       
    52.     //cell选中属性修改为无  
    53.     [cell setSelectionStyle:UITableViewCellSelectionStyleNone];  
    54. }  
    55.   
    56. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{  
    57.       
    58.     static NSString *identifid = @"simpleCell";  
    59.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifid];  
    60.     if(!cell){  
    61.         cell = [[UITableViewCell alloc] init];  
    62.     }  
    63.       
    64.     NSMutableDictionary *dic = [self.voiceArray objectAtIndex:indexPath.row];  
    65.       
    66.     //加载聊天内容  
    67.     UIButton *chatView = [dic objectForKey:@"view"];  
    68.     if([[dic objectForKey:@"from"] isEqualToString:@"SELF"]){  
    69.         //添加录音时长显示  
    70.         UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(120, 25, 30, 30)];  
    71.         int time = [[dic objectForKey:@"time"] intValue];  
    72.         [label setText:[NSString stringWithFormat:@"%d'", time]];  
    73.         [cell addSubview:label];  
    74.           
    75.         //添加头像  
    76.         float offset = (chatView.frame.size.height - 48)>0?(chatView.frame.size.height - 48)/2:10;  
    77.         UIImageView *headIcon = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 48 -5, offset, 48, 48)];  
    78.         [headIcon setImage:[UIImage imageNamed:@"h2.jpg"]];  
    79.         [cell addSubview:headIcon];  
    80.         [chatView setTitle:@"点击播放" forState:UIControlStateNormal];  
    81.           
    82.         chatView.tag = 100 + indexPath.row;  
    83.         [chatView addTarget:self action:@selector(playVoice:) forControlEvents:UIControlEventTouchUpInside];  
    84.           
    85.     }else if([[dic objectForKey:@"from"] isEqualToString:@"OTHER"]){  
    86.         //系统自动回复部分  
    87.         float offset = (chatView.frame.size.height - 48)>0?(chatView.frame.size.height - 48)/2:10;  
    88.         UIImageView *headIcon = [[UIImageView alloc] initWithFrame:CGRectMake(5, offset, 48, 48)];  
    89.         [headIcon setImage:[UIImage imageNamed:@"h1.jpg"]];  
    90.         [cell addSubview:headIcon];  
    91.         [chatView setTitle:@"hello world" forState:UIControlStateNormal];  
    92.     }  
    93.   
    94.     [cell addSubview:chatView];  
    95.       
    96.     return cell;  
    97. }  
    98.   
    99. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{  
    100.     return [_voiceArray count];  
    101. }  
    102.   
    103. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  
    104.     UIView *chatView = [[_voiceArray objectAtIndex:[indexPath row]] objectForKey:@"view"];  
    105.     return chatView.frame.size.height+30;  
    106. }  
    107.   
    108. //添加手势操作,长按按钮  
    109. - (void)handSpeakBtnPressed:(UILongPressGestureRecognizer *)gestureRecognizer {  
    110.     if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {  
    111.         NSLog(@"UIGestureRecognizerStateBegan");  
    112.           
    113.         [self.speekBtb setTitle:@"松开结束" forState:UIControlStateNormal];  
    114.         [self talk:nil];  
    115.     }  
    116.     if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {  
    117.         NSLog(@"UIGestureRecognizerStateChanged");  
    118.     }  
    119.       
    120.     if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {  
    121.         NSLog(@"UIGestureRecognizerStateEnded");  
    122.           
    123.         [self.speekBtb setTitle:@"按住说话" forState:UIControlStateNormal];  
    124.         [self stopRecordVoice];  
    125.     }  
    126. }  
    127.   
    128. //开始录音  
    129. - (IBAction)talk:(id)sender {  
    130.     //若正在播放则立即返回  
    131.     if(self.isPlaying){  
    132.         return;  
    133.     }  
    134.       
    135.     if(!self.isSpeak){  
    136.         self.isSpeak = YES;  
    137.         [RecorderManager sharedManager].delegate = self;  
    138.         [[RecorderManager sharedManager] startRecording];  
    139.     }  
    140. }  
    141.   
    142. //结束录音  
    143. - (void)stopRecordVoice{  
    144.     self.isSpeak = NO;  
    145.     [[RecorderManager sharedManager] stopRecording];  
    146. }  
    147.   
    148. //播放录音  
    149. - (void)playVoice:(id)sender{  
    150.     if(self.isSpeak){  
    151.         return;  
    152.     }  
    153.       
    154.     if(!self.isPlaying){  
    155.         UIButton *btn = (UIButton *)sender;  
    156.         NSInteger index = btn.tag;  
    157.           
    158.         NSMutableDictionary *dic = [_voiceArray objectAtIndex:(index - 100)];  
    159.         self.fileName = [dic objectForKey:@"voice"];  
    160.           
    161.         [PlayerManager sharedManager].delegate = nil;  
    162.           
    163.         self.isPlaying = YES;  
    164.         [[PlayerManager sharedManager] playAudioWithFileName:self.fileName delegate:self];  
    165.     }else{  
    166.         self.isPlaying = NO;  
    167.         [[PlayerManager sharedManager] stopPlaying];  
    168.     }  
    169. }  
    170.   
    171. - (void)recordingFinishedWithFileName:(NSString *)filePath time:(NSTimeInterval)interval{  
    172.     //录音保存的文件地址  
    173.     self.fileName = filePath;  
    174.     UIButton *view = [self bubbleView:@"点击播放" from:YES];  
    175.     //时长  
    176.     NSNumber *num = [[NSNumber alloc] initWithDouble:interval];  
    177.       
    178.     NSMutableDictionary *dic = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"SELF", @"from", view, @"view", self.fileName, @"voice", num, @"time", nil nil];  
    179.     [self.voiceArray addObject:dic];  
    180.       
    181.     //系统默认回复消息  
    182.     UIButton *otherView = [self bubbleView:@"你好!" from:NO];  
    183.     NSMutableDictionary *m_dic = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"OTHER", @"from", otherView, @"view", @"", @"voice", 0, @"time",nil];  
    184.       
    185.     [self.voiceArray addObject:m_dic];  
    186.       
    187.     [_vTableView reloadData];  
    188. }  
    189.   
    190. //超时操作  
    191. - (void)recordingTimeout{  
    192.     self.isSpeak = NO;  
    193. }  
    194.   
    195. //录音机停止采集声音  
    196. - (void)recordingStopped{  
    197.     self.isSpeak = NO;  
    198. }  
    199.   
    200. //录制失败操作  
    201. - (void)recordingFailed:(NSString *)failureInfoString{  
    202.     self.isSpeak = NO;  
    203. }  
    204.   
    205. //播放停止  
    206. - (void)playingStoped{  
    207.     self.isPlaying = NO;  
    208. }  
    209.   
    210. //聊天气泡按钮生成  
    211. - (UIButton*)bubbleView:(NSString *)message from:(BOOL)isFromSelf  
    212. {  
    213.     UIView *returnView = [self assembleMessageAtIndex:message from:isFromSelf];  
    214.     UIButton *cellView = [[UIButton alloc] initWithFrame:CGRectZero];  
    215.     cellView.backgroundColor = [UIColor clearColor];  
    216.     [returnView setBackgroundColor:[UIColor clearColor]];  
    217.       
    218.     NSString *picName = [NSString stringWithFormat:@"%@.png", isFromSelf?@"bubble2":@"bubble1"];  
    219.     UIImage *bubble = [UIImage imageNamed:picName];  
    220.       
    221.     UIImageView *bubbleView = [[UIImageView alloc] initWithImage:[bubble stretchableImageWithLeftCapWidth:35 topCapHeight:3]];  
    222.     if(isFromSelf)  
    223.     {  
    224.         returnView.frame = CGRectMake(9.0f, 20.0f, returnView.frame.size.width, returnView.frame.size.height);  
    225.         bubbleView.frame = CGRectMake(0.0f, 14.0f, returnView.frame.size.width+45.0f, returnView.frame.size.height + 20.0f);  
    226.         cellView.frame = CGRectMake(self.view.frame.size.width - bubbleView.frame.size.width - 60, 20.0f, bubbleView.frame.size.width, bubbleView.frame.size.height + 20.0f);  
    227.     }  
    228.     else  
    229.     {  
    230.         returnView.frame = CGRectMake(88.0f, 20.0f, returnView.frame.size.width, returnView.frame.size.height);  
    231.         bubbleView.frame = CGRectMake(55.0f, 14.0f, returnView.frame.size.width + 45.0f, returnView.frame.size.height + 20.0f);  
    232.         cellView.frame = CGRectMake(50.0f, 20.0f, bubbleView.frame.size.width + 50.0f, bubbleView.frame.size.height + 20.0f);  
    233.     }  
    234.       
    235.     [cellView setBackgroundImage:bubble forState:UIControlStateNormal];  
    236.     [cellView setFont:[UIFont systemFontOfSize:13.0f]];  
    237.     return cellView;  
    238. }  
    239.   
    240. #pragma mark -  
    241. #pragma mark assemble message at index  
    242. #define BUBBLEWIDTH 18  
    243. #define BUBBLEHEIGHT 18  
    244. #define MAX_WIDTH 140  
    245. - (UIView *)assembleMessageAtIndex:(NSString *)message from:(BOOL)fromself  
    246. {  
    247.     NSMutableArray  *array = [[NSMutableArray alloc] init];  
    248.     [self getImageRange:message _array:array];  
    249.       
    250.     UIView *returnView = [[UIView alloc] initWithFrame:CGRectZero];  
    251.     CGFloat upX = 0;  
    252.     CGFloat upY = 0;  
    253.     CGFloat x = 0;  
    254.     CGFloat y = 0;  
    255.       
    256.     if(array)  
    257.     {  
    258.         for(int i = 0; i < [array count]; i++)  
    259.         {  
    260.             NSString *msg = [array objectAtIndex:i];  
    261.               
    262.             for (int index = 0; index < msg.length; index++)  
    263.             {  
    264.                 NSString *m_ch = [msg substringWithRange:NSMakeRange(index, 1)];  
    265.                 if(upX >= MAX_WIDTH)  
    266.                 {  
    267.                     upY = upY + BUBBLEHEIGHT;  
    268.                     upX = 0;  
    269.                     x = 140;  
    270.                     y = upY;  
    271.                 }  
    272.                   
    273.                 UIFont *font = [UIFont systemFontOfSize:13.0f];  
    274.                 CGSize m_size = [m_ch sizeWithFont:font constrainedToSize:CGSizeMake(140, 40)];  
    275.                 UILabel *m_label = [[UILabel alloc] initWithFrame:CGRectMake(upX, upY, m_size.width, m_size.height)];  
    276.                 [returnView addSubview:m_label];  
    277.                 m_label.font = font;  
    278.                 m_label.text = m_ch;  
    279.                 m_label.backgroundColor = [UIColor clearColor];  
    280.                 upX = upX+m_size.width;  
    281.                 if(x < 140)  
    282.                 {  
    283.                     x = upX;  
    284.                 }  
    285.             }  
    286.         }  
    287.     }  
    288.       
    289.     returnView.frame = CGRectMake(15.0f, 1.0f, x, y);  
    290.     return returnView;  
    291. }  
    292.   
    293. - (void) getImageRange:(NSString *)message _array:(NSMutableArray *)array  
    294. {  
    295.     if(message != nil)  
    296.     {  
    297.         [array addObject: message];  
    298.     }  
    299. }  
    300.   
    301.   
    302. - (void)dealloc{  
    303.   
    304.     [self removeObserver:self forKeyPath:@"isSpeak"];  
    305.     self.fileName = nil;  
    306. }  
    307.   
    308. @end  

    好了一个简单的语音聊天程序就好了,是不是很简单,其中最重要的就是 RecorderManager以及PlayerManager两个类了,一个负责录音,一个负责播放,这两个类我准备放到下一篇博客中讲解一下,大家不妨通过去下载我的Demo自己动手试一试,下载地址:http://download.csdn.net/detail/shenjie12345678/8021263。

    注意点:

    1.在将Demo程序中的Classes以及Libs文件加入到工程中去的时候,请将echo_diagnostic.m文件以及以test开头的文件删掉,否则工程会报错。

    2.在工程中将Preprocessor Macros选项中的内容删除。


  • 相关阅读:
    css 分类+选择器
    emmet语法
    程序员能力矩阵
    时间管理

    java 内存 解析
    SQL 查询优化
    2016 书单计划
    ssh框架;
    Mybatis;
  • 原文地址:https://www.cnblogs.com/LGX3399577/p/sfdf.html
Copyright © 2020-2023  润新知