码迷,mamicode.com
首页 > 移动开发 > 详细

iOS语音

时间:2016-07-10 21:44:28      阅读:1003      评论:0      收藏:0      [点我收藏+]

标签:

 

[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选项中的内容删除。

 


 

iOS语音

标签:

原文地址:http://www.cnblogs.com/LGX3399577/p/sfdf.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!