From: http://blog.csdn.net/honghaier/article/details/62494089
” Fangka "Mahjong R&D skills, in the"Red Boy's Game Development Road". Welcome to pay attention to the public number!
Fangka Mahjong Analysis Series of "Thousand-mile Pronunciation"
In the room card game, it is necessary to watch and play cards frequently. In order to communicate in real time, typing and chatting are often troublesome. Through voice communication, reminders can help players express their emotions in time and enhance the atmosphere of the game.
So how does this work?
First, the process is divided into three steps:
1. Recording sound and compressing it into data packets: This process is usually when the player clicks the button, starts recording, loosens the button, stops recording and generates WAV files, and then compresses them into WAV files by encoding conversion.
Here is the basis Android Make a distinction between the two platforms.
-
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 "";
-
}
At Native. Java Achieve recording and end:
-
-
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);
-
-
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;
-
}
In addition, in AndroidMainfest.xml, be aware of opening recording permissions:
-
<uses-permission android:name="android.permission.RECORD_AUDIO" />
iOS Version Processing: You need to complete the corresponding functions in the mm file
-
AVAudioRecorder *recorder = NULL;
-
void IosHelper::beginRecord(const charchar *_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,
-
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
-
nil 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 charchar * IosHelper::endRecord()
-
{
-
if (recorder == nil)
-
return "";
-
if (recorder.isRecording)
-
[recorder stop];
-
return "";
-
}
Second. Send voice data to server: After recording voice and generating file, send the file out.
-
std::string kFileName = JniFun::stopSoundRecord();
-
sendTalkFile(m_pLocal->GetChairID(),kFileName);
This is to send the file in the form of data packets without elaborating.
Third. Receive the data and decompress, play: After receiving the message, write the data to the file and play it.
-
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");
-
-
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;
-
}
In the end, voice chat in room card chess and cards is completely realized. Of course, this method is not perfect, and it would be better if real-time voice conversation in P2P could be opened. In addition, this set of code will continue to produce sound files, which is a problem, small partners can send sound and play sound after deleting the generated sound files, so as not to cause space growth BUG.~
” Fangka "Mahjong R&D skills, in the"Red Boy's Game Development Road". Welcome to pay attention to the public number!