Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
32 kB · 1105 lines
C++
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106#include "stdafx.h"#include <libsysmodule.h>#include <rudp.h>#include <audioin.h>#include <audioout.h>#include <fios2.h>
#include "SonyVoiceChat_Orbis.h"
std::vector<SQRVoiceConnection*> SonyVoiceChat_Orbis::m_remoteConnections;bool SonyVoiceChat_Orbis::m_bVoiceStarted = false;int SonyVoiceChat_Orbis::m_numLocalDevicesConnected = 0; SQRLocalVoiceDevice SonyVoiceChat_Orbis::m_localVoiceDevices[MAX_LOCAL_PLAYER_COUNT];uint32_t SonyVoiceChat_Orbis::m_voiceOutPort;bool SonyVoiceChat_Orbis::m_forceSendPacket = false; // force a packet across the network, even if there's no data, so we can update flagsRingBuffer SonyVoiceChat_Orbis::m_recordRingBuffer(sc_ringBufferSize);VoicePacket::Flags SonyVoiceChat_Orbis::m_localPlayerFlags[MAX_LOCAL_PLAYER_COUNT];bool SonyVoiceChat_Orbis::m_bInitialised = false;CRITICAL_SECTION SonyVoiceChat_Orbis::m_csRemoteConnections;
// sample related variablesSceVoiceStartParam startParam;int32_t playSize = 0;
static const int sc_thresholdValue = 100;
static const bool sc_verbose = false;
// #define _USE_PCM_AUDIO_//#define USE_PCM_MIC_DATA
int g_loadedPCMVoiceDataSizes[4];int g_loadedPCMVoiceDataPos[4];char* g_loadedPCMVoiceData[4];
static void CreatePort(uint32_t *portId, const SceVoicePortParam *pArg){ C4JThread::PushAffinityAllCores(); // PS4 only
int err = sceVoiceCreatePort( portId, pArg ); assert(err == SCE_OK); assert(*portId != SCE_VOICE_INVALID_PORT_ID); C4JThread::PopAffinity(); // PS4 only}
static void DeletePort(uint32_t& port){ int32_t result; if (port != SCE_VOICE_INVALID_PORT_ID) { result = sceVoiceDeletePort( port ); if (result != SCE_OK) { app.DebugPrintf("sceVoiceDeletePort failed %0x\n", result); assert(0); } port = SCE_VOICE_INVALID_PORT_ID; }}
void LoadPCMVoiceData(){ for(int i=0;i<4;i++) { char filename[64]; sprintf(filename, "voice%d.pcm", i+1); HANDLE file = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwHigh=0; g_loadedPCMVoiceDataSizes[i] = GetFileSize(file,&dwHigh);
if(g_loadedPCMVoiceDataSizes[i]!=0) { g_loadedPCMVoiceData[i] = new char[g_loadedPCMVoiceDataSizes[i]]; DWORD bytesRead; BOOL bSuccess = ReadFile(file, g_loadedPCMVoiceData[i], g_loadedPCMVoiceDataSizes[i], &bytesRead, NULL); assert(bSuccess); } g_loadedPCMVoiceDataPos[i] = 0; }}
void SonyVoiceChat_Orbis::init(){ int returnCode = SCE_OK; SceUserServiceUserId initialUserId;
if (returnCode < 0) { app.DebugPrintf("Error: sceSysmoduleLoadModule(SCE_SYSMODULE_VOICE), ret 0x%08x\n", returnCode); assert(0); }
SceVoiceInitParam params; SceVoicePortParam portArgs; memset( ¶ms, 0, sizeof(params) ); params.appType = SCE_VOICE_APPTYPE_GAME; params.onEvent = 0; returnCode = sceVoiceInit( ¶ms , SCE_VOICE_VERSION_100); if (returnCode < 0) { app.DebugPrintf("Error: sceVoiceInit(), ret 0x%08x\n", returnCode); assert(0); }
#ifdef _USE_PCM_AUDIO_ portArgs.portType = SCE_VOICE_PORTTYPE_OUT_PCMAUDIO; portArgs.bMute = false; portArgs.threshold = 0; portArgs.volume = 1.0f; portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; portArgs.pcmaudio.format.sampleRate = SCE_VOICE_SAMPLINGRATE_16000; portArgs.pcmaudio.bufSize = 4096;#else portArgs.portType = SCE_VOICE_PORTTYPE_OUT_VOICE; portArgs.bMute = false; portArgs.threshold = 0; portArgs.volume = 1.0f; portArgs.voice.bitrate = VOICE_ENCODED_FORMAT;#endif CreatePort( &m_voiceOutPort, &portArgs );
start(); m_bInitialised = true; InitializeCriticalSection(&m_csRemoteConnections);}
void SonyVoiceChat_Orbis::start(){ if( m_bVoiceStarted == false) { startParam.container = malloc(SCE_VOICE_MEMORY_CONTAINER_SIZE); startParam.memSize = SCE_VOICE_MEMORY_CONTAINER_SIZE;
int err;
C4JThread::PushAffinityAllCores(); // PS4 only err = sceVoiceStart(&startParam); assert(err == SCE_OK); C4JThread::PopAffinity(); // PS4 only
m_bVoiceStarted = true; }}
void SonyVoiceChat_Orbis::checkFinished(){ EnterCriticalSection(&m_csRemoteConnections);
for(int i=0;i<m_remoteConnections.size();i++) { assert(m_remoteConnections[i]->m_bFlaggedForShutdown); }// assert(m_numLocalDevicesConnected == 0);
LeaveCriticalSection(&m_csRemoteConnections);}
void SonyVoiceChat_Orbis::shutdown(){ m_bInitialised = false; int32_t result; result = sceVoiceStop(); assert(result == SCE_OK); result = sceVoiceEnd(); assert(result == SCE_OK); free(startParam.container);
int returnCode = sceSysmoduleUnloadModule(SCE_SYSMODULE_VOICE); if (returnCode < 0) { app.DebugPrintf("Error: sceSysmoduleUnloadModule(SCE_SYSMODULE_VOICE), ret 0x%08x\n", returnCode); assert(0); }}
void SonyVoiceChat_Orbis::setEnabled( bool bEnabled ){}
// Internal send function. This attempts to send as many elements in the queue as possible until the write function tells us that we can't send any more. This way,// we are guaranteed that if there *is* anything more in the queue left to send, we'll get a CELL_RUDP_CONTEXT_EVENT_WRITABLE event when whatever we've managed to// send here is complete, and can continue on.void SQRVoiceConnection::SendMoreInternal(){ EnterCriticalSection(&m_csQueue); bool keepSending; do { keepSending = false; if( m_sendQueue.size() > 0) { // Attempt to send the full data in the first element in our queue unsigned char *data= m_sendQueue.front().current; int dataSize = m_sendQueue.front().end - m_sendQueue.front().current; int ret = sceRudpWrite( m_rudpCtx, data, dataSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL ); int wouldBlockFlag = SCE_RUDP_ERROR_WOULDBLOCK;
if( ret == dataSize ) { // Fully sent, remove from queue - will loop in the while loop to see if there's anything else in the queue we could send delete [] m_sendQueue.front().start; m_sendQueue.pop(); if( m_sendQueue.size() ) { keepSending = true; } } else if( ( ret >= 0 ) || ( ret == wouldBlockFlag ) ) {
// Things left to send - adjust this element in the queue int remainingBytes; if( ret >= 0 ) { // Only ret bytes sent so far remainingBytes = dataSize - ret; assert(remainingBytes > 0 ); } else { // Is CELL_RUDP_ERROR_WOULDBLOCK, nothing has yet been sent remainingBytes = dataSize; } m_sendQueue.front().current = m_sendQueue.front().end - remainingBytes; } } } while (keepSending); LeaveCriticalSection(&m_csQueue);}
void SQRVoiceConnection::SendInternal(const void *data, unsigned int dataSize){ EnterCriticalSection(&m_csQueue);
QueuedSendBlock sendBlock;
unsigned char *dataCurrent = (unsigned char *)data; unsigned int dataRemaining = dataSize;
while( dataRemaining ) { int dataSize = dataRemaining; if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD; sendBlock.start = new unsigned char [dataSize]; sendBlock.end = sendBlock.start + dataSize; sendBlock.current = sendBlock.start; memcpy( sendBlock.start, dataCurrent, dataSize); m_sendQueue.push(sendBlock); dataRemaining -= dataSize; dataCurrent += dataSize; }
// app.DebugPrintf("voice sent %d bytes\n", dataSize);
// Now try and send as much as we can SendMoreInternal();
LeaveCriticalSection(&m_csQueue);}
void SQRVoiceConnection::readRemoteData(){ unsigned int dataSize = sceRudpGetSizeReadable(m_rudpCtx); if( dataSize > 0 ) { VoicePacket packet; int bytesRead = sceRudpRead( m_rudpCtx, &packet, dataSize, 0, NULL ); unsigned int writeSize; if( bytesRead > 0 ) {// app.DebugPrintf("voice received %d bytes\n", bytesRead); writeSize = bytesRead; packet.verifyData(bytesRead, 19); addPacket(packet);// m_playRingBuffer.Write((char*)data, writeSize);
} }
}
SQRVoiceConnection::SQRVoiceConnection( int rudpCtx, SceNpMatching2RoomMemberId remoteRoomMemberId ) : m_rudpCtx(rudpCtx) , m_remoteRoomMemberId(remoteRoomMemberId) , m_bConnected(false) , m_headsetConnectionMask(0) , m_playRingBuffer(sc_ringBufferSize){ InitializeCriticalSection(&m_csQueue); InitializeCriticalSection(&m_csPacketQueue);
SceVoiceInitParam params; SceVoicePortParam portArgs;#ifdef _USE_PCM_AUDIO_ portArgs.portType = SCE_VOICE_PORTTYPE_IN_PCMAUDIO; portArgs.bMute = false; portArgs.threshold = 100; portArgs.volume = 1.0f; portArgs.pcmaudio.format.sampleRate= SCE_VOICE_SAMPLINGRATE_16000; portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; portArgs.pcmaudio.bufSize = 4096;#else portArgs.portType = SCE_VOICE_PORTTYPE_IN_VOICE; portArgs.bMute = false; portArgs.threshold = sc_thresholdValue; // compensate network jitter portArgs.volume = 1.0f; portArgs.voice.bitrate = VOICE_ENCODED_FORMAT;#endif CreatePort( &m_voiceInPort, &portArgs ); m_nextExpectedFrameIndex = 0; m_bFlaggedForShutdown = false;}
SQRVoiceConnection::~SQRVoiceConnection(){ DeleteCriticalSection(&m_csQueue); DeleteCriticalSection(&m_csPacketQueue); extern int g_numRUDPContextsBound; int err = sceRudpTerminate( m_rudpCtx ); app.DebugPrintf(sc_verbose, "-----------------::::::::::::: sceRudpTerminate\n" );
app.DebugPrintf("-----------------------------\n"); if(err<0) app.DebugPrintf("Voice rudp context failed to delete!!! %d\n", m_rudpCtx); else { g_numRUDPContextsBound--; app.DebugPrintf("Voice rudp context deleted %d\n", m_rudpCtx); } app.DebugPrintf("-----------------------------\n");
DeletePort(m_voiceInPort);
}
bool SQRVoiceConnection::getNextPacket( VoicePacket& packet ){ EnterCriticalSection(&m_csPacketQueue); bool retVal = false; if(m_receivedVoicePackets.size() > 0) { retVal = true; packet = m_receivedVoicePackets.front(); m_receivedVoicePackets.pop(); } LeaveCriticalSection(&m_csPacketQueue); return retVal;}
void SQRVoiceConnection::addPacket( VoicePacket& packet ){ EnterCriticalSection(&m_csPacketQueue); m_receivedVoicePackets.push(packet); LeaveCriticalSection(&m_csPacketQueue);}
int g_frameNum = 0;bool g_bRecording = false;
uint32_t frameSendIndex = 0;uint32_t lastReadFrameCnt = 0;
void PrintAllOutputVoiceStates( std::vector<SQRVoiceConnection*>& connections){ for(int rIdx=0;rIdx<connections.size(); rIdx++) { SQRVoiceConnection* pVoice = connections[rIdx]; SceVoiceBasePortInfo portInfo; int result = sceVoiceGetPortInfo(pVoice->m_voiceInPort, &portInfo ); static SceVoicePortState lastPortState = SCE_VOICE_PORTSTATE_IDLE; if(portInfo.state != lastPortState) { lastPortState = portInfo.state; switch(portInfo.state) { case SCE_VOICE_PORTSTATE_IDLE: app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_IDLE\n"); break; case SCE_VOICE_PORTSTATE_BUFFERING: app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_BUFFERING\n"); break; case SCE_VOICE_PORTSTATE_RUNNING: app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_RUNNING\n"); break; case SCE_VOICE_PORTSTATE_READY: app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_READY\n"); break; case SCE_VOICE_PORTSTATE_NULL: default: app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_NULL\n"); break; } } }
}
void SonyVoiceChat_Orbis::sendPCMMicData(){ int32_t result; uint32_t outputPortBytes; VoicePacket packetToSend; uint32_t readSize; SceVoiceBasePortInfo portInfo; memset( &portInfo, 0, sizeof(portInfo) ); uint16_t frameGap = 0;
DWORD tick = GetTickCount(); static DWORD lastTick = 0; int numFrames = ceilf((tick - lastTick)/16.0f); lastTick = tick; readSize = 512 * numFrames;
if(g_loadedPCMVoiceDataPos[0] + readSize < g_loadedPCMVoiceDataSizes[0]) { for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) { if(m_localVoiceDevices[i].isValid()) { result = sceVoiceWriteToIPort(m_localVoiceDevices[i].m_microphonePort, &g_loadedPCMVoiceData[0][g_loadedPCMVoiceDataPos[0]], &readSize, 0); } } } g_loadedPCMVoiceDataPos[0] += readSize; if(g_loadedPCMVoiceDataPos[0] > (g_loadedPCMVoiceDataSizes[0] + 8192)) g_loadedPCMVoiceDataPos[0] = 0;
}
void SonyVoiceChat_Orbis::sendAllVoiceData(){ int32_t result; uint32_t outputPortBytes; VoicePacket packetToSend; uint32_t readSize; SceVoiceBasePortInfo portInfo; memset( &portInfo, 0, sizeof(portInfo) ); uint16_t frameGap = 0;
VoicePacket::Flags lastPlayerFlags[MAX_LOCAL_PLAYER_COUNT];
for(int i=0; i<MAX_LOCAL_PLAYER_COUNT;i++) lastPlayerFlags[i] = m_localPlayerFlags[i];
bool flagsChanged = false;
// grab the status of all the local voices for(int i=0; i<MAX_LOCAL_PLAYER_COUNT;i++) { if(m_localVoiceDevices[i].isValid()) { bool bChatRestricted = false; ProfileManager.GetChatAndContentRestrictions(i,true,&bChatRestricted,NULL,NULL);
if(bChatRestricted) { m_localPlayerFlags[i].m_bHasMicConnected = false; } else { /* Obtain port state */ int32_t state; int err = sceVoiceGetPortAttr(m_localVoiceDevices[i].m_microphonePort, SCE_VOICE_ATTR_AUDIOINPUT_SILENT_STATE, &state,sizeof(state)); if(err == SCE_OK) { if (state == 0) m_localPlayerFlags[i].m_bHasMicConnected = true; else m_localPlayerFlags[i].m_bHasMicConnected = false; } else m_localPlayerFlags[i].m_bHasMicConnected = false;
} if(m_localPlayerFlags[i].m_bHasMicConnected) { SceVoiceBasePortInfo portInfo; int result = sceVoiceGetPortInfo(m_localVoiceDevices[i].m_microphonePort, &portInfo ); assert(result == SCE_OK); switch(portInfo.state) { case SCE_VOICE_PORTSTATE_READY: case SCE_VOICE_PORTSTATE_BUFFERING: case SCE_VOICE_PORTSTATE_IDLE: m_localPlayerFlags[i].m_bTalking = false; break; case SCE_VOICE_PORTSTATE_RUNNING: m_localPlayerFlags[i].m_bTalking = true; break; default: assert(0); } } else { m_localPlayerFlags[i].m_bTalking = false; } } else { m_localPlayerFlags[i].m_bHasMicConnected = false; m_localPlayerFlags[i].m_bTalking = false; } packetToSend.m_localPlayerFlags[i] = m_localPlayerFlags[i]; if(m_localPlayerFlags[i].m_bHasMicConnected != lastPlayerFlags[i].m_bHasMicConnected || m_localPlayerFlags[i].m_bTalking != lastPlayerFlags[i].m_bTalking) flagsChanged = true; }
if(sc_verbose) { EnterCriticalSection(&m_csRemoteConnections); PrintAllOutputVoiceStates(m_remoteConnections); LeaveCriticalSection(&m_csRemoteConnections); } result = sceVoiceGetPortInfo(m_voiceOutPort, &portInfo ); if (result != SCE_OK) { app.DebugPrintf("sceVoiceGetPortInfo failed %x\n", result); assert(0); }
outputPortBytes = portInfo.numByte; outputPortBytes = (outputPortBytes>sizeof(packetToSend.m_data))?sizeof(packetToSend.m_data):outputPortBytes; if( outputPortBytes || flagsChanged || m_forceSendPacket) { frameSendIndex += lastReadFrameCnt; if(outputPortBytes) { readSize = outputPortBytes; result = sceVoiceReadFromOPort(m_voiceOutPort, packetToSend.m_data, &readSize ); if (result != SCE_OK) { app.DebugPrintf("sceVoiceReadFromOPort failed %0x\n", result); assert(0); return; } lastReadFrameCnt = readSize/portInfo.frameSize; assert(readSize%portInfo.frameSize == 0);
packetToSend.m_numFrames = lastReadFrameCnt; packetToSend.m_frameSendIndex = frameSendIndex; packetToSend.setChecksum(readSize); } else { readSize = 0; packetToSend.m_numFrames = 0; packetToSend.m_frameSendIndex = frameSendIndex; packetToSend.setChecksum(readSize);
}
int packetSize = packetToSend.getPacketSize(readSize);
EnterCriticalSection(&m_csRemoteConnections);
// send this packet out to all our remote connections for(int rIdx=0;rIdx<m_remoteConnections.size(); rIdx++) { SQRVoiceConnection* pVoice = m_remoteConnections[rIdx]; if(pVoice->m_bConnected) m_remoteConnections[rIdx]->SendInternal(&packetToSend, packetSize); }
LeaveCriticalSection(&m_csRemoteConnections); } m_forceSendPacket = false; }
bool g_bPlaying = false;
void SonyVoiceChat_Orbis::playAllReceivedData(){ EnterCriticalSection(&m_csRemoteConnections); // write all the incoming data from the network to each of the input voices for(int rIdx=0;rIdx<m_remoteConnections.size(); rIdx++) { SQRVoiceConnection* pVoice = m_remoteConnections[rIdx]; VoicePacket packet; while(pVoice->getNextPacket(packet)) // MGH - changed to a while loop, so all the packets are sent to the voice port, and it can handle delayed packets due to the size of it's internal buffer { int frameGap; if (pVoice->m_nextExpectedFrameIndex == packet.m_frameSendIndex) { // no voice frame drop, continuous frames frameGap = 0; app.DebugPrintf(sc_verbose, "index@%d gets expected frame\n",pVoice->m_nextExpectedFrameIndex); pVoice->m_nextExpectedFrameIndex = packet.m_frameSendIndex + packet.m_numFrames; } else if (pVoice->m_nextExpectedFrameIndex < packet.m_frameSendIndex) { // has voice frame drop, dropped forwarding frames frameGap = packet.m_frameSendIndex - pVoice->m_nextExpectedFrameIndex; app.DebugPrintf(sc_verbose, "index@%d gets dropped forwarding frames %d\n",pVoice->m_nextExpectedFrameIndex, frameGap); pVoice->m_nextExpectedFrameIndex = packet.m_frameSendIndex + packet.m_numFrames; } else if (pVoice->m_nextExpectedFrameIndex > packet.m_frameSendIndex) { // has voice frame drop, dropped preceding frames, no reset on pVoice->m_nextExpectedFrameIndex frameGap = packet.m_frameSendIndex - pVoice->m_nextExpectedFrameIndex; app.DebugPrintf(sc_verbose, "index@%d gets dropped forwarding frames %d\n", pVoice->m_nextExpectedFrameIndex, frameGap); }
SceVoiceBasePortInfo portInfo; int result = sceVoiceGetPortInfo(pVoice->m_voiceInPort, &portInfo ); if (result != SCE_OK) { app.DebugPrintf(sc_verbose, "sceVoiceGetPortInfo LoopbackVoiceInPort failed %x\n", result); assert(0); LeaveCriticalSection(&m_csRemoteConnections); return; } uint32_t writeSize = packet.m_numFrames * portInfo.frameSize; int inputPortBytes = portInfo.numByte; inputPortBytes = (inputPortBytes>writeSize)?writeSize:inputPortBytes; writeSize = inputPortBytes; result = sceVoiceWriteToIPort(pVoice->m_voiceInPort, packet.m_data, &writeSize, frameGap); if (result != SCE_OK) { app.DebugPrintf(sc_verbose, "sceVoiceWriteToIPort failed %0x\n", result); assert(0); LeaveCriticalSection(&m_csRemoteConnections); return; } if (writeSize != inputPortBytes) { // libvoice internal voice in port buffer fulls app.DebugPrintf(sc_verbose, "internal voice in port buffer fulls. \n"); } packet.m_numFrames = 0;
// copy the flags for(int flagIndex=0;flagIndex<MAX_LOCAL_PLAYER_COUNT;flagIndex++) pVoice->m_remotePlayerFlags[flagIndex] = packet.m_localPlayerFlags[flagIndex]; } } LeaveCriticalSection(&m_csRemoteConnections);
}
void SonyVoiceChat_Orbis::tick(){ if(m_bInitialised) {// DWORD tick = GetTickCount();// static DWORD lastTick = 0;// app.DebugPrintf("Time since last voice tick : %d ms\n", tick - lastTick);// lastTick = tick; g_frameNum++;#ifdef USE_PCM_MIC_DATA sendPCMMicData();#endif sendAllVoiceData(); playAllReceivedData(); EnterCriticalSection(&m_csRemoteConnections); for(int i=m_remoteConnections.size()-1;i>=0;i--) { if(m_remoteConnections[i]->m_bFlaggedForShutdown) { delete m_remoteConnections[i]; m_remoteConnections.erase(m_remoteConnections.begin() + i); } }
LeaveCriticalSection(&m_csRemoteConnections);
// MGH - added to hopefully fix a lockup with shutdowns happening on different threads, when more than 1 player leaves the game for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) { if(m_localVoiceDevices[i].m_bFlaggedForShutdown) { m_localVoiceDevices[i].shutdownWhenFlagged(); } }
}}
bool SonyVoiceChat_Orbis::hasMicConnected(SQRNetworkPlayer* pNetPlayer){ if(pNetPlayer->IsLocal()) { return m_localPlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bHasMicConnected; } else { EnterCriticalSection(&m_csRemoteConnections); for(int i=0;i<m_remoteConnections.size();i++) { SQRVoiceConnection* pVoice = m_remoteConnections[i]; if(pVoice->m_remoteRoomMemberId == pNetPlayer->m_roomMemberId) { bool bMicConnected = pVoice->m_remotePlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bHasMicConnected; LeaveCriticalSection(&m_csRemoteConnections); return bMicConnected; } } LeaveCriticalSection(&m_csRemoteConnections); } // if we get here we've not found the player, panic!! assert(0); return false;}
void SonyVoiceChat_Orbis::mute( bool bMute ){}
void SonyVoiceChat_Orbis::mutePlayer( const SceNpMatching2RoomMemberId member_id, bool bMute ) /*Turn chat audio from a specified player on or off */{}
void SonyVoiceChat_Orbis::muteLocalPlayer( bool bMute ) /*Turn microphone input on or off */{}
bool SonyVoiceChat_Orbis::isMuted(){}
bool SonyVoiceChat_Orbis::isMutedPlayer( const PlayerUID& memberUID) { return false;}
bool SonyVoiceChat_Orbis::isMutedLocalPlayer() { return false;}
bool SonyVoiceChat_Orbis::isTalking(SQRNetworkPlayer* pNetPlayer){ if(pNetPlayer->IsLocal()) { return m_localPlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bTalking; } else { EnterCriticalSection(&m_csRemoteConnections); for(int i=0;i<m_remoteConnections.size();i++) { SQRVoiceConnection* pVoice = m_remoteConnections[i]; if(pVoice->m_remoteRoomMemberId == pNetPlayer->m_roomMemberId) { bool bTalking = pVoice->m_remotePlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bTalking; LeaveCriticalSection(&m_csRemoteConnections); return bTalking; } } LeaveCriticalSection(&m_csRemoteConnections); } // if we get here we've not found the player, panic!! assert(0); return false;}
void SQRLocalVoiceDevice::init(SceUserServiceUserId localUserID, bool bChatRestricted){ SceVoiceInitParam params; SceVoicePortParam portArgs;
int returnCode = 0; m_bChatRestricted = bChatRestricted;
#ifdef USE_PCM_MIC_DATA portArgs.portType = SCE_VOICE_PORTTYPE_IN_PCMAUDIO; portArgs.bMute = false; portArgs.threshold = 100; portArgs.volume = 1.0f; portArgs.pcmaudio.format.sampleRate= SCE_VOICE_SAMPLINGRATE_16000; portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; portArgs.pcmaudio.bufSize = 4096; CreatePort( &m_microphonePort, &portArgs );#else portArgs.portType = SCE_VOICE_PORTTYPE_IN_DEVICE; portArgs.bMute = false; portArgs.threshold = 0; portArgs.volume = 1.0f; portArgs.device.userId = localUserID; portArgs.device.type = SCE_AUDIO_IN_TYPE_VOICE; portArgs.device.index = 0; CreatePort( &m_microphonePort, &portArgs );
#endif portArgs.portType = SCE_VOICE_PORTTYPE_OUT_DEVICE; portArgs.bMute = false; portArgs.threshold = 0; portArgs.volume = 1.0f; portArgs.device.userId = localUserID; portArgs.device.type = SCE_AUDIO_OUT_PORT_TYPE_VOICE; portArgs.device.index = 0; CreatePort( &m_headsetPort, &portArgs );
m_localUserID = localUserID;
}
void SQRLocalVoiceDevice::shutdownWhenFlagged(){
assert(isValid()); m_localUserID = SCE_USER_SERVICE_USER_ID_INVALID; DeletePort(m_microphonePort); DeletePort(m_headsetPort); m_bFlaggedForShutdown = false;}
SQRVoiceConnection* SonyVoiceChat_Orbis::addRemoteConnection( int RudpCxt, SceNpMatching2RoomMemberId peerMemberId){ EnterCriticalSection(&m_csRemoteConnections); SQRVoiceConnection* pConn = new SQRVoiceConnection(RudpCxt, peerMemberId); m_remoteConnections.push_back(pConn); m_forceSendPacket = true; // new connection, so we'll force a packet through for the flags LeaveCriticalSection(&m_csRemoteConnections); return pConn;}
void SonyVoiceChat_Orbis::connectPorts(uint32_t inPort, uint32_t outPort){ int returnCode = sceVoiceConnectIPortToOPort(inPort, outPort); if (returnCode != SCE_OK ) { app.DebugPrintf("sceVoiceConnectIPortToOPort failed (0x%08x), inPort 0x%08x, outPort 0x%08x\n", returnCode, inPort, outPort); assert(0); }}void SonyVoiceChat_Orbis::disconnectPorts(uint32_t inPort, uint32_t outPort){ int returnCode = sceVoiceDisconnectIPortFromOPort(inPort, outPort); if (returnCode != SCE_OK ) { app.DebugPrintf("sceVoiceDisconnectIPortFromOPort failed (0x%08x), inPort 0x%08x, outPort 0x%08x\n", returnCode, inPort, outPort); assert(0); }}
void SonyVoiceChat_Orbis::makeLocalConnections(){ // connect all mics to other devices headsets, for local chat for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) { SQRLocalVoiceDevice* pConnectFrom = &m_localVoiceDevices[i]; if(pConnectFrom->isValid()) { for(int j=0;j<MAX_LOCAL_PLAYER_COUNT;j++) { SQRLocalVoiceDevice* pConnectTo = &m_localVoiceDevices[j]; if( (pConnectFrom!=pConnectTo) && pConnectTo->isValid()) { if(pConnectFrom->m_localConnections[j] == false) { if(pConnectTo->m_bChatRestricted == false && pConnectFrom->m_bChatRestricted == false) { connectPorts(pConnectFrom->m_microphonePort, pConnectTo->m_headsetPort); pConnectFrom->m_localConnections[j] = true; } } } } } }}
void SonyVoiceChat_Orbis::breakLocalConnections(int playerIdx){ // break any connections with devices that are no longer valid for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) { SQRLocalVoiceDevice* pConnectedFrom = &m_localVoiceDevices[i]; for(int j=0;j<MAX_LOCAL_PLAYER_COUNT;j++) { if(pConnectedFrom->m_localConnections[j] == true) { SQRLocalVoiceDevice* pConnectedTo = &m_localVoiceDevices[j]; if(i==playerIdx || j==playerIdx) { if(pConnectedTo->m_bChatRestricted == false && pConnectedFrom->m_bChatRestricted == false) { disconnectPorts(pConnectedFrom->m_microphonePort, pConnectedTo->m_headsetPort); pConnectedFrom->m_localConnections[j] = false; } } } } }}
void SonyVoiceChat_Orbis::initLocalPlayer(int playerIndex){ if(m_localVoiceDevices[playerIndex].isValid() == false) { bool chatRestricted = false; ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL);
// create all device ports required m_localVoiceDevices[playerIndex].init(ProfileManager.getUserID(playerIndex), chatRestricted); m_numLocalDevicesConnected++; if(m_localVoiceDevices[playerIndex].m_bChatRestricted == false) { connectPorts(m_localVoiceDevices[playerIndex].m_microphonePort, m_voiceOutPort); } m_forceSendPacket = true; // new local device, so we'll force a packet through for the flags
} makeLocalConnections();}
void SonyVoiceChat_Orbis::connectPlayer(SQRVoiceConnection* pConnection, int playerIndex){ if((pConnection->m_headsetConnectionMask & (1 << playerIndex)) == 0) { initLocalPlayer(playerIndex); // added this as we can get a client->client connection coming in first, and the network player hasn't been created yet (so this hasn't been initialised) if(m_localVoiceDevices[playerIndex].m_bChatRestricted == false) { connectPorts(pConnection->m_voiceInPort, m_localVoiceDevices[playerIndex].m_headsetPort); } pConnection->m_headsetConnectionMask |= (1 << playerIndex); app.DebugPrintf("Connecting player %d to rudp context %d\n", playerIndex, pConnection->m_rudpCtx); m_forceSendPacket = true; // new connection, so we'll force a packet through for the flags }}
SQRVoiceConnection* SonyVoiceChat_Orbis::GetVoiceConnectionFromRudpCtx( int RudpCtx ){ for(int i=0;i<m_remoteConnections.size();i++) { if(m_remoteConnections[i]->m_rudpCtx == RudpCtx) return m_remoteConnections[i]; } return NULL;}
void SonyVoiceChat_Orbis::connectPlayerToAll( int playerIndex ){ EnterCriticalSection(&m_csRemoteConnections);
for(int i=0;i<m_remoteConnections.size();i++) { SonyVoiceChat_Orbis::connectPlayer(m_remoteConnections[i], playerIndex); }
LeaveCriticalSection(&m_csRemoteConnections);}
SQRVoiceConnection* SonyVoiceChat_Orbis::getVoiceConnectionFromRoomMemberID( SceNpMatching2RoomMemberId roomMemberID ){ for(int i=0;i<m_remoteConnections.size();i++) { if(m_remoteConnections[i]->m_remoteRoomMemberId == roomMemberID) { return m_remoteConnections[i]; } }
return NULL;}
void SonyVoiceChat_Orbis::disconnectLocalPlayer( int localIdx ){ EnterCriticalSection(&m_csRemoteConnections);
if(m_localVoiceDevices[localIdx].m_bChatRestricted == false) { disconnectPorts(m_localVoiceDevices[localIdx].m_microphonePort, m_voiceOutPort); for(int i=0;i<m_remoteConnections.size();i++) { disconnectPorts(m_remoteConnections[i]->m_voiceInPort, m_localVoiceDevices[localIdx].m_headsetPort); m_remoteConnections[i]->m_headsetConnectionMask &= (~(1 << localIdx)); app.DebugPrintf("disconnecting player %d from rudp context %d\n", localIdx, m_remoteConnections[i]->m_rudpCtx); } } LeaveCriticalSection(&m_csRemoteConnections); breakLocalConnections(localIdx); m_localVoiceDevices[localIdx].flagForShutdown(); m_numLocalDevicesConnected--;
if(m_numLocalDevicesConnected == 0) // no more local players, kill all the remote connections { for(int i=0;i<m_remoteConnections.size();i++) { delete m_remoteConnections[i]; } m_remoteConnections.clear(); }}
void SonyVoiceChat_Orbis::disconnectRemoteConnection( SQRVoiceConnection* pVoice ){ EnterCriticalSection(&m_csRemoteConnections);
int voiceIdx = -1; for(int i=0;i<m_remoteConnections.size();i++) { if(m_remoteConnections[i] == pVoice) voiceIdx = i; } assert(voiceIdx>=0); if(voiceIdx>=0) { m_remoteConnections[voiceIdx]->m_bFlaggedForShutdown = true; }
LeaveCriticalSection(&m_csRemoteConnections);
}
void SonyVoiceChat_Orbis::setConnected( int RudpCtx ){ SQRVoiceConnection* pVoice = GetVoiceConnectionFromRudpCtx(RudpCtx); if(pVoice) { pVoice->m_bConnected = true; m_forceSendPacket = true; } else { assert(false); }}
RingBuffer::RingBuffer( int sizeBytes ){ buffer = new char[sizeBytes]; buf_size = sizeBytes; buf_full = buf_free = 0;}
int RingBuffer::Write( char* data, int len_ ){ if (len_ <= 0) return len_; unsigned int len = (unsigned int)len_; unsigned int data_size = buf_size - (buf_free - buf_full); if (len > data_size) len = data_size; data_size = buf_size - (buf_free % buf_size); if (data_size > len) data_size = len; memcpy(buffer + (buf_free % buf_size), data, data_size); if (data_size != len) memcpy(buffer, data + data_size, len - data_size); buf_free += len; return len;}
int RingBuffer::Read( char* data, int max_bytes_ ){ if (max_bytes_ <= 0) return max_bytes_; unsigned int max_bytes = (unsigned int)max_bytes_; unsigned int result = buf_free - buf_full; if (result > max_bytes) result = max_bytes; unsigned int chunk = buf_size - (buf_full % buf_size); if (chunk > result) chunk = result; memcpy(data, buffer + (buf_full % buf_size), chunk); if (chunk != result) memcpy(data + chunk, buffer, result - chunk); buf_full += result; return result;}