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. @interface MainViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, RecordingDelegate, PlayingDelegate, UIGestureRecognizerDelegate>
  5. - (IBAction)talk:(id)sender;
  6. @property (strong, nonatomic) IBOutlet UITableView *vTableView;
  7. @property (strong, nonatomic) IBOutlet UIButton *speekBtb;
  8. @property (assign) BOOL isSpeak;
  9. @property (strong, nonatomic) NSMutableArray *voiceArray;
  10. @property (strong, nonatomic) NSString *fileName;
  11. @property (assign) BOOL isPlaying;
  12. @end

实现:

[objc] view plain copy

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

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

注意点:

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

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

时间: 2024-10-29 22:42:07

iOS语音的相关文章

IOS语音录取

在IOS中,在做语音识别中,需要对语音进行抓取. #import "GetAudioViewController.h" #import <AVFoundation/AVFoundation.h> #import <UIKit/UIKit.h> #import <ImageIO/ImageIO.h> #import <MobileCoreServices/MobileCoreServices.h> #import <QuartzCor

iOS - 语音云通讯

iOS SDK 2.0 语音及图片消息详解本文档将详细介绍融云的语音及图片消息接口功能及使用说明.阅读本文前,我们假设您已经阅读了融云 iOS 开发指南,并掌握融云 SDK 的基本用法. 语音消息用来发送语音片段消息,您可以通过融云客户端 IMLib 接口或 Server API 接口发送语音消息.如果您使用的是融云 IMKit 则该功能已经在 SDK 中封装好,直接使用即可.以下为通过融云 IMLib 及 Server API 发送语音消息的方法. 从客户端发送消息获取要发送的语音数据 wav

iOS语音书写功能(语音转文本)

Demo下载地址 最近在项目开发中,需要将语音识别转换成文本的功能.研究了下科大讯飞,附上Demo分享给大家. 研发前先得做一些准备. 1.注册科大讯飞开发者帐号(http://www.xfyun.cn) 2.下载开发平台(iOS.或android,或其他)所需要的SDK(SDK包含:说明文档.SDK即iflyMSC.framework.Demo) 3.项目中添加SDK(添加时,先将SDK复制粘贴到项目文件,再通过addframe的方法添加到项目引用),及相关联的framework 添加方法:T

ios语音输入崩溃

游戏中任何可以输入的地方,只要调用语音输入,必然会导致app崩溃,解决方法如下: ok, so essentially the gist of it is that siri wants gl context and to be rendered alongside your view. So you need to play nice with it.first of all in Classes/Unity/EAGLContextHelper.hadd forward declaration

iOS语音播放之切换听筒和扬声器的方法解决方案

[[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; //建议在播放之前设置yes,播放结束设置NO,这个功能是开启红外感应 //添加监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification&

iOS语音播放之切换听筒和扬声器

[[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; //建议在播放之前设置yes,播放结束设置NO,这个功能是开启红外感应 //添加监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification&

如何使用 iOS 7 的 AVSpeechSynthesizer 制作有声书(1)

原文: http://www.raywenderlich.com/64623/make-narrated-book-using-avspeechsynthesizer-ios-7 随着 PageViewController 的引入,苹果让开发者们制作图书类app 更加轻松.不幸的是,对于生活在朝九晚五繁忙节奏中的人们来说,阅读也是一件奢侈的事情.为什么你不能在读一本小说的同时做其他事情呢? 在 Siri 刚开始出现的时候,苹果曾经用复杂的动态文本阅读将开发者拒之门外,但当iOS7 发布的时候,苹

使用Olami SDK实现一个语音输入数字进行24点计算的iOS程序

前言 在目前的软件应用中,输入方式还是以文字输入方式为主,但是语音输入的方式目前应用的越来越广泛.这是一个利用 Olami SDK 编写的一个24点iOS程序,是通过语音进行输入. Olami SDK的介绍在下面这个网址 https://cn.olami.ai/wiki/?mp=sdk&content=sdk/ios/reference.html 在这个网址中详细的介绍了Olami SDK包含了那些函数和定义的委托. App实现 下面就通过24点这个程序来介绍一下如何使用这个SDK. 这个APP

Unity3D 语音接入适用于pc、ios、android

语音接入 考虑到pc与ios.android三端的混服情况,所有录音的格式均存储为mp3格式,也是unity推荐的音频文件方式 前提:目前比较成熟的语音模块由科大讯飞平台提供的,目前我们需要的功能是把语音转化成文字,因此我们只需要下载相应的语音识别模块就可以了. 1)进入科大讯飞官网下载相应平台的sdk,目前我们只需要免费的语音识别就可以了,要创建相应的应用才能下载,里面的demo提供边录音边翻译的功能. 2)pc端的没有提供边录边能,要想在pc版进行录音可引入第三方库进行录音或者使用unity