the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
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( ¶ms, 0, sizeof(params) );
101 params.appType = SCE_VOICE_APPTYPE_GAME;
102 params.onEvent = 0;
103 returnCode = sceVoiceInit( ¶ms , 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}