内容简介:房卡麻将分析系列之"千里传音"
”房卡“麻将研发技巧,尽在 ”红孩儿的游戏开发之路“ ,欢迎关注公众号!
房卡麻将分析系列之"千里传音"
在房卡棋牌游戏中,因为要频繁的看牌,出牌。为了实时沟通打字聊天往往比较麻烦,通过语音交流,催牌可以很好的帮助玩家及时的表达情绪,增强游戏的气氛。
那么这是怎么做到的呢?
首先这个过程分为三步:
一。录制声音并压缩成数据包: 这个过程一般是当玩家点击按钮,开始录音,松开按钮,停止录音并生成WAV文件,之后通过编码转换压缩为
在这里要根据安卓和苹果两个平台来做区分。
void startSoundRecord()
{
std::string kFileName = utility::toString(time(NULL),".wav");
s_kRecordFileName = cocos2d::FileUtils::getInstance()->getWritablePath()+kFileName;
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "startSoundRecord", "(Ljava/lang/String;)V");
if (isHave)
{
jstring jurl = minfo.env->NewStringUTF(kFileName.c_str());
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID,jurl);
cocos2d::log("JniFun call startSoundRecord over!");
minfo.env->DeleteLocalRef(minfo.classID);
}
else
{
cocos2d::log("JniFun call startSoundRecord error!");
}
#endif
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
IosHelper::beginRecord(s_kRecordFileName.c_str());
#endif
}
const char* stopSoundRecord()
{
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
std::string str;
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,JAVA_CLASSNAME, "stopSoundRecord", "()Ljava/lang/String;");
if (isHave)
{
jstring jFileName = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
const char *newStr = minfo.env->GetStringUTFChars(jFileName, 0);
str = newStr;
cocos2d::log("JniFun call stopSoundRecord over :");
cocos2d::log("%s",str.c_str());
minfo.env->ReleaseStringUTFChars(jFileName, newStr);
minfo.env->DeleteLocalRef(minfo.classID);
}
else
{
cocos2d::log("JniFun call stopSoundRecord error!");
}
return str.c_str();
#endif
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
IosHelper::endRecord();
return s_kRecordFileName.c_str();
#endif
return "";
}
在Native.java中实现录音和结束:
//开始录音
public static void startSoundRecord( String SoundFileName)
{
String SoundFilePath= Environment.getExternalStorageDirectory().getAbsolutePath();
if (filePath != null)
{
File file = new File(filePath);
if (file!= null && file.exists())
{
file.delete();
}
}
filePath = SoundFilePath+"/"+SoundFileName;
recorder = new MediaRecorder();
//从麦克风中录音
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//设置编码格式为AMR
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(SoundFilePath+"/"+SoundFileName);
try {
recorder.prepare();//
recorder.start();//
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//结束录音
public static String stopSoundRecord()
{
recorder.stop();//
recorder.release(); //
recorder = null;
return filePath;
}
另外,要在AndroidMainfest.xml中注意开启录音权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
IOS版本处理:需要在mm文件中完成相应函数
AVAudioRecorder *recorder = NULL;
void IosHelper::beginRecord(const char *_fileName)
{
if (recorder == nil)
{
//设置文件名和录音路径
NSString *recordFilePath = [NSString stringWithCString:_fileName encoding:NSUTF8StringEncoding];
NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithFloat: 8000.0],AVSampleRateKey, //采样率
[NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采样位数 默认 16
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,//通道的数目
nil];
//初始化录音
NSError *error = nil;
recorder = [[ AVAudioRecorder alloc] initWithURL:[NSURL URLWithString:recordFilePath] settings:recordSetting error:&error];
}
recorder.meteringEnabled = YES;
[recorder prepareToRecord];
//开始录音
UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
// 扬声器播放
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[recorder record];
}
const char * IosHelper::endRecord()
{
if (recorder == nil)
return "";
if (recorder.isRecording)
[recorder stop];
return "";
}
二。发送声音数据到服务器: 在结束录制声音并生成文件后,将文件发送出去。
std::string kFileName = JniFun::stopSoundRecord(); sendTalkFile(m_pLocal->GetChairID(),kFileName);
这里就是将文件以数据包形式发送出去,不做详细表述。
三。接收数据并解压,播放: 在接收到消息后,将数据写入文件并播放即可。
bool GameBase::RevTalk_File(CMD_GR_C_TableTalk* pNetInfo)
{
if (pNetInfo->strTalkSize == 0)
{
return true;
}
static int iIdex = 0;
iIdex ++;
std::string kFile = utility::toString(cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(),"TableTalk",iIdex,".arm");
FILE *fp = fopen(kFile.c_str(), "wb");
fseek(fp,0,SEEK_END);
fseek(fp,0,SEEK_SET);
fwrite(&pNetInfo->strTalkData,sizeof(unsigned char), pNetInfo->strTalkSize,fp);
fclose(fp);
int iAddTime = pNetInfo->strTalkSize/1200+2.0f;
if (iAddTime > 10)
{
iAddTime = 10;
}
std::string kDestFile = kFile;
utility::StringReplace(kDestFile,"arm","wav");
//这里需要做一个解压转换,将ARM转换成WAV
ArmFun::ArmToWav(kFile.c_str(),kDestFile.c_str());
//为了防止游戏音乐干扰,先静音游戏音乐
SoundFun::Instance().PaseBackMusic();
SoundFun::Instance().ResumeBackMusic(iAddTime);
SoundFun::Instance().PaseEffectMusic();
SoundFun::Instance().ResumeEffectMusic(iAddTime);
//播放接收到的声音文件
SoundFun::Instance().playEffectDirect(kDestFile);
//指定玩家显示播放语音的动画图标
GamePlayer* pPlayer = getBasePlayerByChairID(pNetInfo->cbChairID);
if (pPlayer)
{
pPlayer->showTalkState(pNetInfo);
}
return true;
}
最终,房卡棋牌中的语音聊天就完整的实现出来了,当然,这种方式并不完美,如果能开启P2P的实时语音对话就更好了。另外,这套代码中会不断的产生声音文件,这是个问题,小伙伴们可以在发送完声音和播放完声音后删除生成的声音文件,以免造成空间增长的BUG~
”房卡“麻将研发技巧,尽在 ”红孩儿的游戏开发之路“ ,欢迎关注公众号!
以上所述就是小编给大家介绍的《房卡麻将分析系列之"千里传音"》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 原创干货!麻将平胡算法 原 荐
- 微软超级麻将AI Suphx论文发布,研发团队深度揭秘技术细节
- 天凤十段,微软超级麻将 AI Suphx 的技术思路与细节
- 天凤十段,微软超级麻将 AI Suphx 的技术思路与细节
- 国内首例!脑机芯片让瘫痪患者用意念喝可乐、打麻将
- 破解非完美信息场景应用,微软公布专业十段麻将AI技术细节
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
明解C语言(第3版)
[日] 柴田望洋 / 管杰、罗勇、杜晓静 / 人民邮电出版社 / 2015-11-1 / 79.00元
本书是日本的C语言经典教材,自出版以来不断重印、修订,被誉为“C语言圣经”。 本书图文并茂,示例丰富,第3版从190段代码和164幅图表增加至205段代码和220幅图表,对C语言的基础知识进行了彻底剖析,内容涉及数组、函数、指针、文件操作等。对于C语言语法以及一些难以理解的概念,均以精心绘制的示意图,清晰、通俗地进行讲解。原著在日本广受欢迎,始终位于网上书店C语言著作排行榜首位。一起来看看 《明解C语言(第3版)》 这本书的介绍吧!