the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1105 lines 32 kB view raw
1#include "stdafx.h" 2#include <libsysmodule.h> 3#include <rudp.h> 4#include <audioin.h> 5#include <audioout.h> 6#include <fios2.h> 7 8#include "SonyVoiceChat_Orbis.h" 9 10std::vector<SQRVoiceConnection*> SonyVoiceChat_Orbis::m_remoteConnections; 11bool SonyVoiceChat_Orbis::m_bVoiceStarted = false; 12int SonyVoiceChat_Orbis::m_numLocalDevicesConnected = 0; 13SQRLocalVoiceDevice SonyVoiceChat_Orbis::m_localVoiceDevices[MAX_LOCAL_PLAYER_COUNT]; 14uint32_t SonyVoiceChat_Orbis::m_voiceOutPort; 15bool SonyVoiceChat_Orbis::m_forceSendPacket = false; // force a packet across the network, even if there's no data, so we can update flags 16RingBuffer SonyVoiceChat_Orbis::m_recordRingBuffer(sc_ringBufferSize); 17VoicePacket::Flags SonyVoiceChat_Orbis::m_localPlayerFlags[MAX_LOCAL_PLAYER_COUNT]; 18bool SonyVoiceChat_Orbis::m_bInitialised = false; 19CRITICAL_SECTION SonyVoiceChat_Orbis::m_csRemoteConnections; 20 21// sample related variables 22SceVoiceStartParam startParam; 23int32_t playSize = 0; 24 25static const int sc_thresholdValue = 100; 26 27static const bool sc_verbose = false; 28 29// #define _USE_PCM_AUDIO_ 30//#define USE_PCM_MIC_DATA 31 32 33 34int g_loadedPCMVoiceDataSizes[4]; 35int g_loadedPCMVoiceDataPos[4]; 36char* g_loadedPCMVoiceData[4]; 37 38static void CreatePort(uint32_t *portId, const SceVoicePortParam *pArg) 39{ 40 C4JThread::PushAffinityAllCores(); // PS4 only 41 42 int err = sceVoiceCreatePort( portId, pArg ); 43 assert(err == SCE_OK); 44 assert(*portId != SCE_VOICE_INVALID_PORT_ID); 45 C4JThread::PopAffinity(); // PS4 only 46} 47 48static void DeletePort(uint32_t& port) 49{ 50 int32_t result; 51 if (port != SCE_VOICE_INVALID_PORT_ID) 52 { 53 result = sceVoiceDeletePort( port ); 54 if (result != SCE_OK) 55 { 56 app.DebugPrintf("sceVoiceDeletePort failed %0x\n", result); 57 assert(0); 58 } 59 port = SCE_VOICE_INVALID_PORT_ID; 60 } 61} 62 63 64void LoadPCMVoiceData() 65{ 66 for(int i=0;i<4;i++) 67 { 68 char filename[64]; 69 sprintf(filename, "voice%d.pcm", i+1); 70 HANDLE file = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 71 DWORD dwHigh=0; 72 g_loadedPCMVoiceDataSizes[i] = GetFileSize(file,&dwHigh); 73 74 if(g_loadedPCMVoiceDataSizes[i]!=0) 75 { 76 g_loadedPCMVoiceData[i] = new char[g_loadedPCMVoiceDataSizes[i]]; 77 DWORD bytesRead; 78 BOOL bSuccess = ReadFile(file, g_loadedPCMVoiceData[i], g_loadedPCMVoiceDataSizes[i], &bytesRead, NULL); 79 assert(bSuccess); 80 } 81 g_loadedPCMVoiceDataPos[i] = 0; 82 } 83} 84 85 86void SonyVoiceChat_Orbis::init() 87{ 88 int returnCode = SCE_OK; 89 SceUserServiceUserId initialUserId; 90 91 if (returnCode < 0) 92 { 93 app.DebugPrintf("Error: sceSysmoduleLoadModule(SCE_SYSMODULE_VOICE), ret 0x%08x\n", returnCode); 94 assert(0); 95 } 96 97 98 SceVoiceInitParam params; 99 SceVoicePortParam portArgs; 100 memset( &params, 0, sizeof(params) ); 101 params.appType = SCE_VOICE_APPTYPE_GAME; 102 params.onEvent = 0; 103 returnCode = sceVoiceInit( &params , SCE_VOICE_VERSION_100); 104 if (returnCode < 0) 105 { 106 app.DebugPrintf("Error: sceVoiceInit(), ret 0x%08x\n", returnCode); 107 assert(0); 108 } 109 110#ifdef _USE_PCM_AUDIO_ 111 portArgs.portType = SCE_VOICE_PORTTYPE_OUT_PCMAUDIO; 112 portArgs.bMute = false; 113 portArgs.threshold = 0; 114 portArgs.volume = 1.0f; 115 portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; 116 portArgs.pcmaudio.format.sampleRate = SCE_VOICE_SAMPLINGRATE_16000; 117 portArgs.pcmaudio.bufSize = 4096; 118#else 119 portArgs.portType = SCE_VOICE_PORTTYPE_OUT_VOICE; 120 portArgs.bMute = false; 121 portArgs.threshold = 0; 122 portArgs.volume = 1.0f; 123 portArgs.voice.bitrate = VOICE_ENCODED_FORMAT; 124#endif 125 CreatePort( &m_voiceOutPort, &portArgs ); 126 127 start(); 128 m_bInitialised = true; 129 InitializeCriticalSection(&m_csRemoteConnections); 130} 131 132 133void SonyVoiceChat_Orbis::start() 134{ 135 if( m_bVoiceStarted == false) 136 { 137 startParam.container = malloc(SCE_VOICE_MEMORY_CONTAINER_SIZE); 138 startParam.memSize = SCE_VOICE_MEMORY_CONTAINER_SIZE; 139 140 int err; 141 142 C4JThread::PushAffinityAllCores(); // PS4 only 143 err = sceVoiceStart(&startParam); 144 assert(err == SCE_OK); 145 C4JThread::PopAffinity(); // PS4 only 146 147 m_bVoiceStarted = true; 148 } 149} 150 151void SonyVoiceChat_Orbis::checkFinished() 152{ 153 EnterCriticalSection(&m_csRemoteConnections); 154 155 for(int i=0;i<m_remoteConnections.size();i++) 156 { 157 assert(m_remoteConnections[i]->m_bFlaggedForShutdown); 158 } 159// assert(m_numLocalDevicesConnected == 0); 160 161 LeaveCriticalSection(&m_csRemoteConnections); 162} 163 164 165void SonyVoiceChat_Orbis::shutdown() 166{ 167 m_bInitialised = false; 168 int32_t result; 169 result = sceVoiceStop(); 170 assert(result == SCE_OK); 171 result = sceVoiceEnd(); 172 assert(result == SCE_OK); 173 free(startParam.container); 174 175 int returnCode = sceSysmoduleUnloadModule(SCE_SYSMODULE_VOICE); 176 if (returnCode < 0) 177 { 178 app.DebugPrintf("Error: sceSysmoduleUnloadModule(SCE_SYSMODULE_VOICE), ret 0x%08x\n", returnCode); 179 assert(0); 180 } 181} 182 183void SonyVoiceChat_Orbis::setEnabled( bool bEnabled ) 184{ 185} 186 187 188 189// 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, 190// 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 191// send here is complete, and can continue on. 192void SQRVoiceConnection::SendMoreInternal() 193{ 194 EnterCriticalSection(&m_csQueue); 195 bool keepSending; 196 do 197 { 198 keepSending = false; 199 if( m_sendQueue.size() > 0) 200 { 201 // Attempt to send the full data in the first element in our queue 202 unsigned char *data= m_sendQueue.front().current; 203 int dataSize = m_sendQueue.front().end - m_sendQueue.front().current; 204 int ret = sceRudpWrite( m_rudpCtx, data, dataSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL ); 205 int wouldBlockFlag = SCE_RUDP_ERROR_WOULDBLOCK; 206 207 if( ret == dataSize ) 208 { 209 // Fully sent, remove from queue - will loop in the while loop to see if there's anything else in the queue we could send 210 delete [] m_sendQueue.front().start; 211 m_sendQueue.pop(); 212 if( m_sendQueue.size() ) 213 { 214 keepSending = true; 215 } 216 } 217 else if( ( ret >= 0 ) || ( ret == wouldBlockFlag ) ) 218 { 219 220 221 // Things left to send - adjust this element in the queue 222 int remainingBytes; 223 if( ret >= 0 ) 224 { 225 // Only ret bytes sent so far 226 remainingBytes = dataSize - ret; 227 assert(remainingBytes > 0 ); 228 } 229 else 230 { 231 // Is CELL_RUDP_ERROR_WOULDBLOCK, nothing has yet been sent 232 remainingBytes = dataSize; 233 } 234 m_sendQueue.front().current = m_sendQueue.front().end - remainingBytes; 235 } 236 } 237 } while (keepSending); 238 LeaveCriticalSection(&m_csQueue); 239} 240 241void SQRVoiceConnection::SendInternal(const void *data, unsigned int dataSize) 242{ 243 EnterCriticalSection(&m_csQueue); 244 245 QueuedSendBlock sendBlock; 246 247 unsigned char *dataCurrent = (unsigned char *)data; 248 unsigned int dataRemaining = dataSize; 249 250 while( dataRemaining ) 251 { 252 int dataSize = dataRemaining; 253 if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD; 254 sendBlock.start = new unsigned char [dataSize]; 255 sendBlock.end = sendBlock.start + dataSize; 256 sendBlock.current = sendBlock.start; 257 memcpy( sendBlock.start, dataCurrent, dataSize); 258 m_sendQueue.push(sendBlock); 259 dataRemaining -= dataSize; 260 dataCurrent += dataSize; 261 } 262 263// app.DebugPrintf("voice sent %d bytes\n", dataSize); 264 265 // Now try and send as much as we can 266 SendMoreInternal(); 267 268 LeaveCriticalSection(&m_csQueue); 269} 270 271void SQRVoiceConnection::readRemoteData() 272{ 273 unsigned int dataSize = sceRudpGetSizeReadable(m_rudpCtx); 274 if( dataSize > 0 ) 275 { 276 VoicePacket packet; 277 int bytesRead = sceRudpRead( m_rudpCtx, &packet, dataSize, 0, NULL ); 278 unsigned int writeSize; 279 if( bytesRead > 0 ) 280 { 281// app.DebugPrintf("voice received %d bytes\n", bytesRead); 282 writeSize = bytesRead; 283 packet.verifyData(bytesRead, 19); 284 addPacket(packet); 285// m_playRingBuffer.Write((char*)data, writeSize); 286 287 } 288 } 289 290} 291 292 293 294SQRVoiceConnection::SQRVoiceConnection( int rudpCtx, SceNpMatching2RoomMemberId remoteRoomMemberId ) 295 : m_rudpCtx(rudpCtx) 296 , m_remoteRoomMemberId(remoteRoomMemberId) 297 , m_bConnected(false) 298 , m_headsetConnectionMask(0) 299 , m_playRingBuffer(sc_ringBufferSize) 300{ 301 InitializeCriticalSection(&m_csQueue); 302 InitializeCriticalSection(&m_csPacketQueue); 303 304 SceVoiceInitParam params; 305 SceVoicePortParam portArgs; 306#ifdef _USE_PCM_AUDIO_ 307 portArgs.portType = SCE_VOICE_PORTTYPE_IN_PCMAUDIO; 308 portArgs.bMute = false; 309 portArgs.threshold = 100; 310 portArgs.volume = 1.0f; 311 portArgs.pcmaudio.format.sampleRate= SCE_VOICE_SAMPLINGRATE_16000; 312 portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; 313 portArgs.pcmaudio.bufSize = 4096; 314#else 315 portArgs.portType = SCE_VOICE_PORTTYPE_IN_VOICE; 316 portArgs.bMute = false; 317 portArgs.threshold = sc_thresholdValue; // compensate network jitter 318 portArgs.volume = 1.0f; 319 portArgs.voice.bitrate = VOICE_ENCODED_FORMAT; 320#endif 321 CreatePort( &m_voiceInPort, &portArgs ); 322 m_nextExpectedFrameIndex = 0; 323 m_bFlaggedForShutdown = false; 324} 325 326SQRVoiceConnection::~SQRVoiceConnection() 327{ 328 DeleteCriticalSection(&m_csQueue); 329 DeleteCriticalSection(&m_csPacketQueue); 330 extern int g_numRUDPContextsBound; 331 int err = sceRudpTerminate( m_rudpCtx ); 332 app.DebugPrintf(sc_verbose, "-----------------::::::::::::: sceRudpTerminate\n" ); 333 334 app.DebugPrintf("-----------------------------\n"); 335 if(err<0) 336 app.DebugPrintf("Voice rudp context failed to delete!!! %d\n", m_rudpCtx); 337 else 338 { 339 g_numRUDPContextsBound--; 340 app.DebugPrintf("Voice rudp context deleted %d\n", m_rudpCtx); 341 } 342 app.DebugPrintf("-----------------------------\n"); 343 344 DeletePort(m_voiceInPort); 345 346} 347 348bool SQRVoiceConnection::getNextPacket( VoicePacket& packet ) 349{ 350 EnterCriticalSection(&m_csPacketQueue); 351 bool retVal = false; 352 if(m_receivedVoicePackets.size() > 0) 353 { 354 retVal = true; 355 packet = m_receivedVoicePackets.front(); 356 m_receivedVoicePackets.pop(); 357 } 358 LeaveCriticalSection(&m_csPacketQueue); 359 return retVal; 360} 361 362void SQRVoiceConnection::addPacket( VoicePacket& packet ) 363{ 364 EnterCriticalSection(&m_csPacketQueue); 365 m_receivedVoicePackets.push(packet); 366 LeaveCriticalSection(&m_csPacketQueue); 367} 368 369int g_frameNum = 0; 370bool g_bRecording = false; 371 372 373uint32_t frameSendIndex = 0; 374uint32_t lastReadFrameCnt = 0; 375 376 377void PrintAllOutputVoiceStates( std::vector<SQRVoiceConnection*>& connections) 378{ 379 for(int rIdx=0;rIdx<connections.size(); rIdx++) 380 { 381 SQRVoiceConnection* pVoice = connections[rIdx]; 382 SceVoiceBasePortInfo portInfo; 383 int result = sceVoiceGetPortInfo(pVoice->m_voiceInPort, &portInfo ); 384 static SceVoicePortState lastPortState = SCE_VOICE_PORTSTATE_IDLE; 385 if(portInfo.state != lastPortState) 386 { 387 lastPortState = portInfo.state; 388 switch(portInfo.state) 389 { 390 case SCE_VOICE_PORTSTATE_IDLE: 391 app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_IDLE\n"); 392 break; 393 case SCE_VOICE_PORTSTATE_BUFFERING: 394 app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_BUFFERING\n"); 395 break; 396 case SCE_VOICE_PORTSTATE_RUNNING: 397 app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_RUNNING\n"); 398 break; 399 case SCE_VOICE_PORTSTATE_READY: 400 app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_READY\n"); 401 break; 402 case SCE_VOICE_PORTSTATE_NULL: 403 default: 404 app.DebugPrintf(" ----- SCE_VOICE_PORTSTATE_NULL\n"); 405 break; 406 } 407 } 408 } 409 410} 411 412 413void SonyVoiceChat_Orbis::sendPCMMicData() 414{ 415 int32_t result; 416 uint32_t outputPortBytes; 417 VoicePacket packetToSend; 418 uint32_t readSize; 419 SceVoiceBasePortInfo portInfo; 420 memset( &portInfo, 0, sizeof(portInfo) ); 421 uint16_t frameGap = 0; 422 423 DWORD tick = GetTickCount(); 424 static DWORD lastTick = 0; 425 int numFrames = ceilf((tick - lastTick)/16.0f); 426 lastTick = tick; 427 readSize = 512 * numFrames; 428 429 if(g_loadedPCMVoiceDataPos[0] + readSize < g_loadedPCMVoiceDataSizes[0]) 430 { 431 for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) 432 { 433 if(m_localVoiceDevices[i].isValid()) 434 { 435 result = sceVoiceWriteToIPort(m_localVoiceDevices[i].m_microphonePort, &g_loadedPCMVoiceData[0][g_loadedPCMVoiceDataPos[0]], &readSize, 0); 436 } 437 } 438 } 439 g_loadedPCMVoiceDataPos[0] += readSize; 440 if(g_loadedPCMVoiceDataPos[0] > (g_loadedPCMVoiceDataSizes[0] + 8192)) 441 g_loadedPCMVoiceDataPos[0] = 0; 442 443 444} 445 446void SonyVoiceChat_Orbis::sendAllVoiceData() 447{ 448 int32_t result; 449 uint32_t outputPortBytes; 450 VoicePacket packetToSend; 451 uint32_t readSize; 452 SceVoiceBasePortInfo portInfo; 453 memset( &portInfo, 0, sizeof(portInfo) ); 454 uint16_t frameGap = 0; 455 456 VoicePacket::Flags lastPlayerFlags[MAX_LOCAL_PLAYER_COUNT]; 457 458 for(int i=0; i<MAX_LOCAL_PLAYER_COUNT;i++) 459 lastPlayerFlags[i] = m_localPlayerFlags[i]; 460 461 bool flagsChanged = false; 462 463 464 465 // grab the status of all the local voices 466 for(int i=0; i<MAX_LOCAL_PLAYER_COUNT;i++) 467 { 468 if(m_localVoiceDevices[i].isValid()) 469 { 470 bool bChatRestricted = false; 471 ProfileManager.GetChatAndContentRestrictions(i,true,&bChatRestricted,NULL,NULL); 472 473 if(bChatRestricted) 474 { 475 m_localPlayerFlags[i].m_bHasMicConnected = false; 476 } 477 else 478 { 479 /* Obtain port state */ 480 int32_t state; 481 int err = sceVoiceGetPortAttr(m_localVoiceDevices[i].m_microphonePort, SCE_VOICE_ATTR_AUDIOINPUT_SILENT_STATE, &state,sizeof(state)); 482 if(err == SCE_OK) 483 { 484 if (state == 0) 485 m_localPlayerFlags[i].m_bHasMicConnected = true; 486 else 487 m_localPlayerFlags[i].m_bHasMicConnected = false; 488 } 489 else 490 m_localPlayerFlags[i].m_bHasMicConnected = false; 491 492 } 493 494 if(m_localPlayerFlags[i].m_bHasMicConnected) 495 { 496 SceVoiceBasePortInfo portInfo; 497 int result = sceVoiceGetPortInfo(m_localVoiceDevices[i].m_microphonePort, &portInfo ); 498 assert(result == SCE_OK); 499 switch(portInfo.state) 500 { 501 case SCE_VOICE_PORTSTATE_READY: 502 case SCE_VOICE_PORTSTATE_BUFFERING: 503 case SCE_VOICE_PORTSTATE_IDLE: 504 m_localPlayerFlags[i].m_bTalking = false; 505 break; 506 case SCE_VOICE_PORTSTATE_RUNNING: 507 m_localPlayerFlags[i].m_bTalking = true; 508 break; 509 default: 510 assert(0); 511 } 512 } 513 else 514 { 515 m_localPlayerFlags[i].m_bTalking = false; 516 } 517 } 518 else 519 { 520 m_localPlayerFlags[i].m_bHasMicConnected = false; 521 m_localPlayerFlags[i].m_bTalking = false; 522 } 523 packetToSend.m_localPlayerFlags[i] = m_localPlayerFlags[i]; 524 if(m_localPlayerFlags[i].m_bHasMicConnected != lastPlayerFlags[i].m_bHasMicConnected || 525 m_localPlayerFlags[i].m_bTalking != lastPlayerFlags[i].m_bTalking) 526 flagsChanged = true; 527 } 528 529 530 if(sc_verbose) 531 { 532 EnterCriticalSection(&m_csRemoteConnections); 533 PrintAllOutputVoiceStates(m_remoteConnections); 534 LeaveCriticalSection(&m_csRemoteConnections); 535 } 536 result = sceVoiceGetPortInfo(m_voiceOutPort, &portInfo ); 537 if (result != SCE_OK) 538 { 539 app.DebugPrintf("sceVoiceGetPortInfo failed %x\n", result); 540 assert(0); 541 } 542 543 544 545 546 outputPortBytes = portInfo.numByte; 547 outputPortBytes = (outputPortBytes>sizeof(packetToSend.m_data))?sizeof(packetToSend.m_data):outputPortBytes; 548 if( outputPortBytes || flagsChanged || m_forceSendPacket) 549 { 550 frameSendIndex += lastReadFrameCnt; 551 if(outputPortBytes) 552 { 553 readSize = outputPortBytes; 554 result = sceVoiceReadFromOPort(m_voiceOutPort, packetToSend.m_data, &readSize ); 555 if (result != SCE_OK) 556 { 557 app.DebugPrintf("sceVoiceReadFromOPort failed %0x\n", result); 558 assert(0); 559 return; 560 } 561 lastReadFrameCnt = readSize/portInfo.frameSize; 562 assert(readSize%portInfo.frameSize == 0); 563 564 packetToSend.m_numFrames = lastReadFrameCnt; 565 packetToSend.m_frameSendIndex = frameSendIndex; 566 packetToSend.setChecksum(readSize); 567 } 568 else 569 { 570 readSize = 0; 571 packetToSend.m_numFrames = 0; 572 packetToSend.m_frameSendIndex = frameSendIndex; 573 packetToSend.setChecksum(readSize); 574 575 } 576 577 578 int packetSize = packetToSend.getPacketSize(readSize); 579 580 EnterCriticalSection(&m_csRemoteConnections); 581 582 // send this packet out to all our remote connections 583 for(int rIdx=0;rIdx<m_remoteConnections.size(); rIdx++) 584 { 585 SQRVoiceConnection* pVoice = m_remoteConnections[rIdx]; 586 if(pVoice->m_bConnected) 587 m_remoteConnections[rIdx]->SendInternal(&packetToSend, packetSize); 588 } 589 590 LeaveCriticalSection(&m_csRemoteConnections); 591 } 592 m_forceSendPacket = false; 593} 594 595bool g_bPlaying = false; 596 597void SonyVoiceChat_Orbis::playAllReceivedData() 598{ 599 EnterCriticalSection(&m_csRemoteConnections); 600 // write all the incoming data from the network to each of the input voices 601 for(int rIdx=0;rIdx<m_remoteConnections.size(); rIdx++) 602 { 603 SQRVoiceConnection* pVoice = m_remoteConnections[rIdx]; 604 VoicePacket packet; 605 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 606 { 607 int frameGap; 608 if (pVoice->m_nextExpectedFrameIndex == packet.m_frameSendIndex) 609 { 610 // no voice frame drop, continuous frames 611 frameGap = 0; 612 app.DebugPrintf(sc_verbose, "index@%d gets expected frame\n",pVoice->m_nextExpectedFrameIndex); 613 pVoice->m_nextExpectedFrameIndex = packet.m_frameSendIndex + packet.m_numFrames; 614 } 615 else if (pVoice->m_nextExpectedFrameIndex < packet.m_frameSendIndex) 616 { 617 // has voice frame drop, dropped forwarding frames 618 frameGap = packet.m_frameSendIndex - pVoice->m_nextExpectedFrameIndex; 619 app.DebugPrintf(sc_verbose, "index@%d gets dropped forwarding frames %d\n",pVoice->m_nextExpectedFrameIndex, frameGap); 620 pVoice->m_nextExpectedFrameIndex = packet.m_frameSendIndex + packet.m_numFrames; 621 } 622 else if (pVoice->m_nextExpectedFrameIndex > packet.m_frameSendIndex) 623 { 624 // has voice frame drop, dropped preceding frames, no reset on pVoice->m_nextExpectedFrameIndex 625 frameGap = packet.m_frameSendIndex - pVoice->m_nextExpectedFrameIndex; 626 app.DebugPrintf(sc_verbose, "index@%d gets dropped forwarding frames %d\n", pVoice->m_nextExpectedFrameIndex, frameGap); 627 } 628 629 SceVoiceBasePortInfo portInfo; 630 int result = sceVoiceGetPortInfo(pVoice->m_voiceInPort, &portInfo ); 631 if (result != SCE_OK) 632 { 633 app.DebugPrintf(sc_verbose, "sceVoiceGetPortInfo LoopbackVoiceInPort failed %x\n", result); 634 assert(0); 635 LeaveCriticalSection(&m_csRemoteConnections); 636 return; 637 } 638 uint32_t writeSize = packet.m_numFrames * portInfo.frameSize; 639 int inputPortBytes = portInfo.numByte; 640 inputPortBytes = (inputPortBytes>writeSize)?writeSize:inputPortBytes; 641 writeSize = inputPortBytes; 642 result = sceVoiceWriteToIPort(pVoice->m_voiceInPort, packet.m_data, &writeSize, frameGap); 643 if (result != SCE_OK) 644 { 645 app.DebugPrintf(sc_verbose, "sceVoiceWriteToIPort failed %0x\n", result); 646 assert(0); 647 LeaveCriticalSection(&m_csRemoteConnections); 648 return; 649 } 650 if (writeSize != inputPortBytes) 651 { 652 // libvoice internal voice in port buffer fulls 653 app.DebugPrintf(sc_verbose, "internal voice in port buffer fulls. \n"); 654 } 655 packet.m_numFrames = 0; 656 657 // copy the flags 658 for(int flagIndex=0;flagIndex<MAX_LOCAL_PLAYER_COUNT;flagIndex++) 659 pVoice->m_remotePlayerFlags[flagIndex] = packet.m_localPlayerFlags[flagIndex]; 660 } 661 } 662 LeaveCriticalSection(&m_csRemoteConnections); 663 664} 665 666void SonyVoiceChat_Orbis::tick() 667{ 668 if(m_bInitialised) 669 { 670// DWORD tick = GetTickCount(); 671// static DWORD lastTick = 0; 672// app.DebugPrintf("Time since last voice tick : %d ms\n", tick - lastTick); 673// lastTick = tick; 674 g_frameNum++; 675#ifdef USE_PCM_MIC_DATA 676 sendPCMMicData(); 677#endif 678 sendAllVoiceData(); 679 playAllReceivedData(); 680 681 EnterCriticalSection(&m_csRemoteConnections); 682 683 for(int i=m_remoteConnections.size()-1;i>=0;i--) 684 { 685 if(m_remoteConnections[i]->m_bFlaggedForShutdown) 686 { 687 delete m_remoteConnections[i]; 688 m_remoteConnections.erase(m_remoteConnections.begin() + i); 689 } 690 } 691 692 LeaveCriticalSection(&m_csRemoteConnections); 693 694 // MGH - added to hopefully fix a lockup with shutdowns happening on different threads, when more than 1 player leaves the game 695 for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) 696 { 697 if(m_localVoiceDevices[i].m_bFlaggedForShutdown) 698 { 699 m_localVoiceDevices[i].shutdownWhenFlagged(); 700 } 701 } 702 703 } 704} 705 706 707 708bool SonyVoiceChat_Orbis::hasMicConnected(SQRNetworkPlayer* pNetPlayer) 709{ 710 if(pNetPlayer->IsLocal()) 711 { 712 return m_localPlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bHasMicConnected; 713 } 714 else 715 { 716 EnterCriticalSection(&m_csRemoteConnections); 717 for(int i=0;i<m_remoteConnections.size();i++) 718 { 719 SQRVoiceConnection* pVoice = m_remoteConnections[i]; 720 if(pVoice->m_remoteRoomMemberId == pNetPlayer->m_roomMemberId) 721 { 722 bool bMicConnected = pVoice->m_remotePlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bHasMicConnected; 723 LeaveCriticalSection(&m_csRemoteConnections); 724 return bMicConnected; 725 } 726 } 727 LeaveCriticalSection(&m_csRemoteConnections); 728 } 729 // if we get here we've not found the player, panic!! 730 assert(0); 731 return false; 732} 733 734void SonyVoiceChat_Orbis::mute( bool bMute ) 735{ 736} 737 738void SonyVoiceChat_Orbis::mutePlayer( const SceNpMatching2RoomMemberId member_id, bool bMute ) /*Turn chat audio from a specified player on or off */ 739{ 740} 741 742void SonyVoiceChat_Orbis::muteLocalPlayer( bool bMute ) /*Turn microphone input on or off */ 743{ 744} 745 746bool SonyVoiceChat_Orbis::isMuted() 747{ 748} 749 750bool SonyVoiceChat_Orbis::isMutedPlayer( const PlayerUID& memberUID) 751{ 752 return false; 753} 754 755bool SonyVoiceChat_Orbis::isMutedLocalPlayer() 756{ 757 return false; 758} 759 760 761bool SonyVoiceChat_Orbis::isTalking(SQRNetworkPlayer* pNetPlayer) 762{ 763 if(pNetPlayer->IsLocal()) 764 { 765 return m_localPlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bTalking; 766 } 767 else 768 { 769 EnterCriticalSection(&m_csRemoteConnections); 770 for(int i=0;i<m_remoteConnections.size();i++) 771 { 772 SQRVoiceConnection* pVoice = m_remoteConnections[i]; 773 if(pVoice->m_remoteRoomMemberId == pNetPlayer->m_roomMemberId) 774 { 775 bool bTalking = pVoice->m_remotePlayerFlags[pNetPlayer->GetLocalPlayerIndex()].m_bTalking; 776 LeaveCriticalSection(&m_csRemoteConnections); 777 return bTalking; 778 } 779 } 780 LeaveCriticalSection(&m_csRemoteConnections); 781 } 782 // if we get here we've not found the player, panic!! 783 assert(0); 784 return false; 785} 786 787 788void SQRLocalVoiceDevice::init(SceUserServiceUserId localUserID, bool bChatRestricted) 789{ 790 SceVoiceInitParam params; 791 SceVoicePortParam portArgs; 792 793 int returnCode = 0; 794 m_bChatRestricted = bChatRestricted; 795 796#ifdef USE_PCM_MIC_DATA 797 portArgs.portType = SCE_VOICE_PORTTYPE_IN_PCMAUDIO; 798 portArgs.bMute = false; 799 portArgs.threshold = 100; 800 portArgs.volume = 1.0f; 801 portArgs.pcmaudio.format.sampleRate= SCE_VOICE_SAMPLINGRATE_16000; 802 portArgs.pcmaudio.format.dataType = SCE_VOICE_PCM_SHORT_LITTLE_ENDIAN; 803 portArgs.pcmaudio.bufSize = 4096; 804 CreatePort( &m_microphonePort, &portArgs ); 805#else 806 portArgs.portType = SCE_VOICE_PORTTYPE_IN_DEVICE; 807 portArgs.bMute = false; 808 portArgs.threshold = 0; 809 portArgs.volume = 1.0f; 810 portArgs.device.userId = localUserID; 811 portArgs.device.type = SCE_AUDIO_IN_TYPE_VOICE; 812 portArgs.device.index = 0; 813 CreatePort( &m_microphonePort, &portArgs ); 814 815#endif 816 portArgs.portType = SCE_VOICE_PORTTYPE_OUT_DEVICE; 817 portArgs.bMute = false; 818 portArgs.threshold = 0; 819 portArgs.volume = 1.0f; 820 portArgs.device.userId = localUserID; 821 portArgs.device.type = SCE_AUDIO_OUT_PORT_TYPE_VOICE; 822 portArgs.device.index = 0; 823 CreatePort( &m_headsetPort, &portArgs ); 824 825 m_localUserID = localUserID; 826 827} 828 829 830 831void SQRLocalVoiceDevice::shutdownWhenFlagged() 832{ 833 834 assert(isValid()); 835 m_localUserID = SCE_USER_SERVICE_USER_ID_INVALID; 836 DeletePort(m_microphonePort); 837 DeletePort(m_headsetPort); 838 m_bFlaggedForShutdown = false; 839} 840 841 842 843SQRVoiceConnection* SonyVoiceChat_Orbis::addRemoteConnection( int RudpCxt, SceNpMatching2RoomMemberId peerMemberId) 844{ 845 EnterCriticalSection(&m_csRemoteConnections); 846 SQRVoiceConnection* pConn = new SQRVoiceConnection(RudpCxt, peerMemberId); 847 m_remoteConnections.push_back(pConn); 848 m_forceSendPacket = true; // new connection, so we'll force a packet through for the flags 849 LeaveCriticalSection(&m_csRemoteConnections); 850 851 return pConn; 852} 853 854void SonyVoiceChat_Orbis::connectPorts(uint32_t inPort, uint32_t outPort) 855{ 856 int returnCode = sceVoiceConnectIPortToOPort(inPort, outPort); 857 if (returnCode != SCE_OK ) 858 { 859 app.DebugPrintf("sceVoiceConnectIPortToOPort failed (0x%08x), inPort 0x%08x, outPort 0x%08x\n", returnCode, inPort, outPort); 860 assert(0); 861 } 862} 863void SonyVoiceChat_Orbis::disconnectPorts(uint32_t inPort, uint32_t outPort) 864{ 865 int returnCode = sceVoiceDisconnectIPortFromOPort(inPort, outPort); 866 if (returnCode != SCE_OK ) 867 { 868 app.DebugPrintf("sceVoiceDisconnectIPortFromOPort failed (0x%08x), inPort 0x%08x, outPort 0x%08x\n", returnCode, inPort, outPort); 869 assert(0); 870 } 871} 872 873 874void SonyVoiceChat_Orbis::makeLocalConnections() 875{ 876 // connect all mics to other devices headsets, for local chat 877 for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) 878 { 879 SQRLocalVoiceDevice* pConnectFrom = &m_localVoiceDevices[i]; 880 if(pConnectFrom->isValid()) 881 { 882 for(int j=0;j<MAX_LOCAL_PLAYER_COUNT;j++) 883 { 884 SQRLocalVoiceDevice* pConnectTo = &m_localVoiceDevices[j]; 885 if( (pConnectFrom!=pConnectTo) && pConnectTo->isValid()) 886 { 887 if(pConnectFrom->m_localConnections[j] == false) 888 { 889 if(pConnectTo->m_bChatRestricted == false && pConnectFrom->m_bChatRestricted == false) 890 { 891 connectPorts(pConnectFrom->m_microphonePort, pConnectTo->m_headsetPort); 892 pConnectFrom->m_localConnections[j] = true; 893 } 894 } 895 } 896 } 897 } 898 } 899} 900 901void SonyVoiceChat_Orbis::breakLocalConnections(int playerIdx) 902{ 903 // break any connections with devices that are no longer valid 904 for(int i=0;i<MAX_LOCAL_PLAYER_COUNT;i++) 905 { 906 SQRLocalVoiceDevice* pConnectedFrom = &m_localVoiceDevices[i]; 907 for(int j=0;j<MAX_LOCAL_PLAYER_COUNT;j++) 908 { 909 if(pConnectedFrom->m_localConnections[j] == true) 910 { 911 SQRLocalVoiceDevice* pConnectedTo = &m_localVoiceDevices[j]; 912 if(i==playerIdx || j==playerIdx) 913 { 914 if(pConnectedTo->m_bChatRestricted == false && pConnectedFrom->m_bChatRestricted == false) 915 { 916 disconnectPorts(pConnectedFrom->m_microphonePort, pConnectedTo->m_headsetPort); 917 pConnectedFrom->m_localConnections[j] = false; 918 } 919 } 920 } 921 } 922 } 923} 924 925 926void SonyVoiceChat_Orbis::initLocalPlayer(int playerIndex) 927{ 928 if(m_localVoiceDevices[playerIndex].isValid() == false) 929 { 930 bool chatRestricted = false; 931 ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); 932 933 // create all device ports required 934 m_localVoiceDevices[playerIndex].init(ProfileManager.getUserID(playerIndex), chatRestricted); 935 m_numLocalDevicesConnected++; 936 if(m_localVoiceDevices[playerIndex].m_bChatRestricted == false) 937 { 938 connectPorts(m_localVoiceDevices[playerIndex].m_microphonePort, m_voiceOutPort); 939 } 940 m_forceSendPacket = true; // new local device, so we'll force a packet through for the flags 941 942 } 943 makeLocalConnections(); 944} 945 946void SonyVoiceChat_Orbis::connectPlayer(SQRVoiceConnection* pConnection, int playerIndex) 947{ 948 if((pConnection->m_headsetConnectionMask & (1 << playerIndex)) == 0) 949 { 950 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) 951 if(m_localVoiceDevices[playerIndex].m_bChatRestricted == false) 952 { 953 connectPorts(pConnection->m_voiceInPort, m_localVoiceDevices[playerIndex].m_headsetPort); 954 } 955 pConnection->m_headsetConnectionMask |= (1 << playerIndex); 956 app.DebugPrintf("Connecting player %d to rudp context %d\n", playerIndex, pConnection->m_rudpCtx); 957 m_forceSendPacket = true; // new connection, so we'll force a packet through for the flags 958 } 959} 960 961SQRVoiceConnection* SonyVoiceChat_Orbis::GetVoiceConnectionFromRudpCtx( int RudpCtx ) 962{ 963 for(int i=0;i<m_remoteConnections.size();i++) 964 { 965 if(m_remoteConnections[i]->m_rudpCtx == RudpCtx) 966 return m_remoteConnections[i]; 967 } 968 return NULL; 969} 970 971void SonyVoiceChat_Orbis::connectPlayerToAll( int playerIndex ) 972{ 973 EnterCriticalSection(&m_csRemoteConnections); 974 975 for(int i=0;i<m_remoteConnections.size();i++) 976 { 977 SonyVoiceChat_Orbis::connectPlayer(m_remoteConnections[i], playerIndex); 978 } 979 980 LeaveCriticalSection(&m_csRemoteConnections); 981} 982 983SQRVoiceConnection* SonyVoiceChat_Orbis::getVoiceConnectionFromRoomMemberID( SceNpMatching2RoomMemberId roomMemberID ) 984{ 985 for(int i=0;i<m_remoteConnections.size();i++) 986 { 987 if(m_remoteConnections[i]->m_remoteRoomMemberId == roomMemberID) 988 { 989 return m_remoteConnections[i]; 990 } 991 } 992 993 return NULL; 994} 995 996void SonyVoiceChat_Orbis::disconnectLocalPlayer( int localIdx ) 997{ 998 EnterCriticalSection(&m_csRemoteConnections); 999 1000 if(m_localVoiceDevices[localIdx].m_bChatRestricted == false) 1001 { 1002 disconnectPorts(m_localVoiceDevices[localIdx].m_microphonePort, m_voiceOutPort); 1003 1004 for(int i=0;i<m_remoteConnections.size();i++) 1005 { 1006 disconnectPorts(m_remoteConnections[i]->m_voiceInPort, m_localVoiceDevices[localIdx].m_headsetPort); 1007 m_remoteConnections[i]->m_headsetConnectionMask &= (~(1 << localIdx)); 1008 app.DebugPrintf("disconnecting player %d from rudp context %d\n", localIdx, m_remoteConnections[i]->m_rudpCtx); 1009 } 1010 } 1011 LeaveCriticalSection(&m_csRemoteConnections); 1012 1013 breakLocalConnections(localIdx); 1014 m_localVoiceDevices[localIdx].flagForShutdown(); 1015 m_numLocalDevicesConnected--; 1016 1017 if(m_numLocalDevicesConnected == 0) // no more local players, kill all the remote connections 1018 { 1019 for(int i=0;i<m_remoteConnections.size();i++) 1020 { 1021 delete m_remoteConnections[i]; 1022 } 1023 m_remoteConnections.clear(); 1024 } 1025} 1026 1027 1028void SonyVoiceChat_Orbis::disconnectRemoteConnection( SQRVoiceConnection* pVoice ) 1029{ 1030 EnterCriticalSection(&m_csRemoteConnections); 1031 1032 int voiceIdx = -1; 1033 for(int i=0;i<m_remoteConnections.size();i++) 1034 { 1035 if(m_remoteConnections[i] == pVoice) 1036 voiceIdx = i; 1037 } 1038 assert(voiceIdx>=0); 1039 if(voiceIdx>=0) 1040 { 1041 m_remoteConnections[voiceIdx]->m_bFlaggedForShutdown = true; 1042 } 1043 1044 LeaveCriticalSection(&m_csRemoteConnections); 1045 1046} 1047 1048void SonyVoiceChat_Orbis::setConnected( int RudpCtx ) 1049{ 1050 SQRVoiceConnection* pVoice = GetVoiceConnectionFromRudpCtx(RudpCtx); 1051 if(pVoice) 1052 { 1053 pVoice->m_bConnected = true; 1054 m_forceSendPacket = true; 1055 } 1056 else 1057 { 1058 assert(false); 1059 } 1060} 1061 1062 1063 1064 1065RingBuffer::RingBuffer( int sizeBytes ) 1066{ 1067 buffer = new char[sizeBytes]; 1068 buf_size = sizeBytes; 1069 buf_full = buf_free = 0; 1070} 1071 1072 1073int RingBuffer::Write( char* data, int len_ ) 1074{ 1075 if (len_ <= 0) return len_; 1076 unsigned int len = (unsigned int)len_; 1077 unsigned int data_size = buf_size - (buf_free - buf_full); 1078 if (len > data_size) 1079 len = data_size; 1080 data_size = buf_size - (buf_free % buf_size); 1081 if (data_size > len) 1082 data_size = len; 1083 memcpy(buffer + (buf_free % buf_size), data, data_size); 1084 if (data_size != len) 1085 memcpy(buffer, data + data_size, len - data_size); 1086 buf_free += len; 1087 return len; 1088} 1089 1090int RingBuffer::Read( char* data, int max_bytes_ ) 1091{ 1092 if (max_bytes_ <= 0) return max_bytes_; 1093 unsigned int max_bytes = (unsigned int)max_bytes_; 1094 unsigned int result = buf_free - buf_full; 1095 if (result > max_bytes) 1096 result = max_bytes; 1097 unsigned int chunk = buf_size - (buf_full % buf_size); 1098 if (chunk > result) 1099 chunk = result; 1100 memcpy(data, buffer + (buf_full % buf_size), chunk); 1101 if (chunk != result) 1102 memcpy(data + chunk, buffer, result - chunk); 1103 buf_full += result; 1104 return result; 1105}