cocos2dx之 android/ios语音交互(二)
来源:互联网 发布:淘宝店铺营销推广 编辑:程序博客网 时间:2024/06/08 14:43
经过一番折腾,终于找到了一种第三方库来转换android与iOS录音播放格式不兼容的问题。
思路:android/iOS手机录音传给服务器,参数(录音数据+手机端口类型),然后等到服务器广播数据给玩家,判断端口是android,将数据保存为为.amr格式,否则保存为.aac格式。不同手机端口调用相应端口函数。
1、设置端口录音格式:
android–>.amr
public void record(){ if (isRecording == true ) return; recondPath = Environment.getExternalStorageDirectory().getAbsolutePath(); recondPath += "/ione1.amr"; //录音格式 File dirs = new File(recondPath); if (dirs.exists()){ dirs.delete(); } stopRecorder(); isRecording = true; mRecorder = new MediaRecorder(); //设置音源为Micphone mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); //设置封装格式 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); //设置编码格式 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mRecorder. setAudioEncodingBitRate(8);//设置音频编码录音比特率 mRecorder.setAudioChannels(1);//设置录制的音频通道数 mRecorder.setAudioSamplingRate(8000); //设置音频采样率记录 mRecorder.setOutputFile(recondPath); try { mRecorder.prepare(); } catch (IOException e) { Log.e(TAG, "prepare() failed"); } //录音 mRecorder.start(); } public boolean stopRecorder() { if( mRecorder == null ) return false; try{ mRecorder.stop(); mRecorder.reset(); mRecorder.release(); mRecorder = null; }catch ( IllegalStateException e){ e.printStackTrace(); } return false; }
ios–>.aac
-(void)startAudioRecording{ if(!isRecording) { [self init]; isRecording = YES; NSLog(@"正在录音"); NSMutableDictionary *dicM=[NSMutableDictionary dictionary]; //设置录音格式 [dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];//录音格式 //设置录音采样率,8000是电话采样率,对于一般录音已经够了 [dicM setObject:@(1600) forKey:AVSampleRateKey]; //设置通道,这里采用单声道 [dicM setObject:@(1) forKey:AVNumberOfChannelsKey]; //每个采样点位数,分为8、16、24、32 [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey]; //录音的质量 [dicM setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey]; //是否使用浮点数采样 [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey]; recorder = [[AVAudioRecorder alloc] initWithURL:recordedFile settings:dicM error:nil]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [[AVAudioSession sharedInstance] setActive:YES error:nil]; [self setSoundSession]; [recorder peakPowerForChannel:0]; [recorder prepareToRecord]; [recorder record]; }}
2、接收服务器传来的需要播放的录音数据,根据不同端口录的音保存为数据相同录音格式:
android–>.amr
ios–>.aac
//服务器传来录音数据,保存在表voiceTab中//voiceTab[index] = event.datafunction MainScene:startPlayVoice() if self.isStartRecond == false then -- 没有在录音 if device.platform == "android" or device.platform == "ios" then --播放录音 local len = #voiceTab if len >= 1 then voicePlay( data ) else print(" 录音播放完了 ") end end endend
function voicePlay(data) if device.platform == "android" then local function callback(result) -- print("录音播放完成 " ) ReturnRecordingPlayChange(result) end local path = writefileCheckRecond( data.voicebin, data.content ) print("开始播放了 voicePlay ") local args = { 1, path, callback } local sigs = "(ILjava/lang/String;I)I" local luaj = require "cocos.cocos2d.luaj" local className = "com/cocos2dx/sample/LuaJavaBridge" local ok,ret = luaj.callStaticMethod(className,"sendLuaToJavaAudioRecorPlay",args,sigs) if not ok then print("luaj error:", ret) else print("The ret is:", ret) end elseif device.platform == "ios" then local path = writefileCheckRecond( data.voicebin, data.content ) print("开始播放了 voicePlay ",path) local i = iosAudioStartPlay( path ) endend
function writefileCheckRecond( data,platform ) local path = device.writablePath.."netSprite/" --获取本地存储目录 if not io.exists(path) then lfs.mkdir(path) --目录不存在,创建此目录 end if platform == "android" then path = path.."recond.amr" elseif platform == "ios" then path = path.."recond.aac" else return; end print("写入完成:"..path) return path;end
3、分析两端口录音互相播放的情况(A端口录音–>B端口播放)
android–>android:android玩家录音为.amr传给服务器,android玩家接收录音二进制数据保存的也是.amr格式,播放OK。
public void startPlay(String filePath,int luaFunc){ if( isPlay == true) { Log.d("tag", "正在播放中"); return; } try { stopPlay(); isPlay = true; playLuaFun = luaFunc; mPlayer = MediaPlayer.create(Cocos2dxActivity.getInstance(), Uri.parse(filePath)); mPlayer.start();// 开始播放 mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ @Override public void onCompletion(MediaPlayer m) { Log.d("tag", "播放完毕"); LuaJavaBridge.callbackLuaFun("1","ReturnRecordingPlayChange",index++); buySuccessJava(1); Log.d(TAG, "playLuaFun = " + playLuaFun); isPlay = false; stopPlay(); } }); }catch(Exception e){ Log.e(TAG, "prepare() failed"); } }
android–>iOS:android玩家录音为.amr传给服务器,iOS玩家接收录音二进制数据保存为.amr格式,调用第三方库将格式.amr转.mav格式就播放OK。
-(void)playAudio{ if(!isPlay) { if([player isPlaying]) { NSLog(@"停止录音播放"); [player pause]; } else { NSString *documentsDirectory= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; audioRecoderSavePath=[NSString stringWithFormat:@"%@/%@", documentsDirectory,@"netSprite/"]; recoderName= [NSString stringWithFormat:@"%@",@"recond.amr"]; tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName]; fm = [NSFileManager defaultManager]; //创建文件管理对象 if([fm fileExistsAtPath:tempRecoderPath] == NO)//判断文件是否存在 { NSLog(@"文件不存在"); recoderName= [NSString stringWithFormat:@"%@",@"recond.aac"]; tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName]; isIos = true; [self startPlayAudio]; return; } else { isIos = false; NSLog(@"文件存在"); } NSString *recoderWavName= [NSString stringWithFormat:@"%@",@"recond.wav"]; tempWavRecoderPath =[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderWavName]; //第三方库AudioConverter [AudioConverter convertAmrToWavAtPath:tempRecoderPath wavSavePath:tempWavRecoderPath asynchronize:YES completion:^(BOOL success, NSString * _Nullable resultPath) { if (success) { NSLog(@"amr转wav成功!"); _wavFilePath = resultPath; [self startPlayAudio]; } else { NSLog(@"amr转wav失败!"); } }]; } }}
iOS –>android:ios玩家录音为.aac格式传给服务器,android玩家接收录音二进制数据保存为.aac格式,
android玩家播iOS录的.aac格式OK。
iOS–>iOS:ios玩家录音为.aac格式传给服务器,ios玩家接收录音二进制数据保存为.aac格式,ios玩家播iOS录的.aac格式OK。
参考:
http://blog.csdn.net/qq_36946260/article/details/69224150
http://blog.csdn.net/adalu1986/article/details/50502387
http://www.jianshu.com/p/7dc01b48f8fc
- cocos2dx之 android/ios语音交互(二)
- cocos2dx之 android/ios语音交互(一)
- Android添加语音交互
- android 发送语音功能和ios交互格式aac
- Android开发之语音合成及听写(二)
- Android-谷歌语音识别之离线识别(二)
- Cocos2dx之libcurl (二)
- android之基于百度语音合讯飞语音识别的语音交互
- cocos2dx之友盟统计(android/ios)
- Android基础之Fragment与Activity交互详解(二)
- 【COCOS2DX-ANDROID-游戏开发之二二】之 调用Cocos2dxGLSurfaceView
- iOS编程技巧总结之语音篇(二)- OpenEars框架及其使用1
- IOS开发之使用Speex格式实现简单的语音聊天功能(二)
- IOS开发之使用Speex格式实现简单的语音聊天功能(二)
- 语音识别之portaudio入门教程(二)
- 【H5+ & Quick-cocos2dx整合】之iOS 二 集成H5+ SDK
- Adobe源码泄漏?3行代码搞定,Flash动画无缝导入Android/iOS/cocos2dx(二)
- 语音识别,语义理解一站式解决之二(android,olami)
- 内网穿透技术详解 --- Java本地项目,可以让别人通过外网访问 (natapp、ngrok、nat123、花生壳等)
- define,const和enmu的区别
- ios-动态改变高度的注意点
- @RequestMapping注解的使用
- paxos工程中的运用-multi-paxos
- cocos2dx之 android/ios语音交互(二)
- java扫描器
- Java内存溢出和内存泄露
- 逻辑回归知识点
- 通过反射得到model的真实类型
- 嵌入式编程 while(1)的妙用!
- 深度学习之基础模型-VGG
- floyd最小环
- 不同数据类型数据的比较大小