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