#include "stdafx.h" /* SCE CONFIDENTIAL PlayStation(R)3 Programmer Tool Runtime Library 430.001 * Copyright (C) 2008 Sony Computer Entertainment Inc. * All Rights Reserved. */ #include "SonyVoiceChat.h" #include /* inet_ntoa() */ /* for displaying extra information */ #ifndef _CONTENT_PACKAGE #define AVC2_GAME_DEBUG #endif #ifdef AVC2_GAME_DEBUG #define INF(...) printf( "INF:" __VA_ARGS__ ) #define ERR(...) printf( "ERR:" __VA_ARGS__ ) #else #define INF(...) #define ERR(...) #endif #define UNUSED_VARIABLE(x) (void)(x) //#define DISABLE_VOICE_CHAT static CellSysutilAvc2InitParam g_chat_avc2param; EAVCEvent SonyVoiceChat::sm_event = AVC_EVENT_EPSILON; EAVCState SonyVoiceChat::sm_state = AVC_STATE_IDLE; SQRNetworkManager_PS3* SonyVoiceChat::sm_pNetworkManager; bool SonyVoiceChat::sm_bEnabled = true; uint8_t SonyVoiceChat::sm_micStatus = CELL_AVC2_MIC_STATUS_UNKNOWN; bool SonyVoiceChat::sm_bLoaded = false; bool SonyVoiceChat::sm_bUnloading = false; unordered_map SonyVoiceChat::sm_bTalkingMap; bool SonyVoiceChat::sm_bCanStart = false; bool SonyVoiceChat::sm_isChatRestricted = false; int SonyVoiceChat::sm_currentBitrate = 28000; void SonyVoiceChat::init( SQRNetworkManager_PS3* pNetMan ) { if(sm_state != AVC_STATE_IDLE) return; sm_pNetworkManager = pNetMan; setState(AVC_STATE_CHAT_INIT); ProfileManager.GetChatAndContentRestrictions(0,false,&sm_isChatRestricted,NULL,NULL); } void SonyVoiceChat::shutdown() { if( sm_state == AVC_STATE_IDLE || sm_state == AVC_STATE_CHAT_LEAVE || sm_state == AVC_STATE_CHAT_UNLOAD || sm_state == AVC_STATE_CHAT_RESET ) { // we're either shut down already, or in the process return; } setEvent(AVC_EVENT_EXIT_GAME); } void SonyVoiceChat::setEnabled( bool bEnabled ) { if(sm_bEnabled != bEnabled) { if(sm_bCanStart) { if(bEnabled) startStream(); else stopStream(); } sm_bEnabled = bEnabled; } } int SonyVoiceChat::eventcb_load(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { int ret = CELL_OK; UNUSED_VARIABLE( event_param ); UNUSED_VARIABLE( userdata ); if( event_id == CELL_AVC2_EVENT_LOAD_SUCCEEDED ) { INF( "CELL_AVC2_EVENT_LOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_CHAT_LOAD_SUCCEEDED); sm_bLoaded = true; // set the packet contention value here CellSysutilAvc2Attribute attr; memset( &attr, 0x00, sizeof(attr) ); attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION; attr.attr_param.int_param = 3; int ret = cellSysutilAvc2SetAttribute(&attr); if( ret != CELL_OK ) { app.DebugPrintf("CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_PACKET_CONTENTION failed !!! 0x%08x\n", ret); } } else /* if( event_id == CELL_AVC2_EVENT_LOAD_FAILED ) */ { INF( "CELL_AVC2_EVENT_LOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_CHAT_LOAD_FAILED); } return ret; } int SonyVoiceChat::eventcb_join(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { int ret = CELL_OK; UNUSED_VARIABLE( event_param ); UNUSED_VARIABLE( userdata ); if( event_id == CELL_AVC2_EVENT_JOIN_SUCCEEDED ) { INF( "CELL_AVC2_EVENT_JOIN_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_CHAT_JOIN_SUCCEEDED); } else /* if( event_id == CELL_AVC2_EVENT_JOIN_FAILED ) */ { INF( "CELL_AVC2_EVENT_JOIN_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_ERROR); } sm_bTalkingMap.clear(); return ret; } int SonyVoiceChat::eventcb_leave( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { int ret = CELL_OK; UNUSED_VARIABLE( event_param ); UNUSED_VARIABLE( userdata ); if( event_id == CELL_AVC2_EVENT_LEAVE_SUCCEEDED ) { INF( "CELL_AVC2_EVENT_LEAVE_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setState(AVC_STATE_CHAT_LEAVE); setEvent(AVC_EVENT_CHAT_LEAVE_SUCCEEDED); } else /* if( event_id == CELL_AVC2_EVENT_LEAVE_FAILED ) */ { INF( "CELL_AVC2_EVENT_LEAVE_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setState(AVC_STATE_CHAT_LEAVE); setEvent(AVC_EVENT_ERROR); } return ret; } int SonyVoiceChat::eventcb_unload(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { int ret = CELL_OK; UNUSED_VARIABLE( event_param ); UNUSED_VARIABLE( userdata ); if( event_id == CELL_AVC2_EVENT_UNLOAD_SUCCEEDED ) { INF( "CELL_AVC2_EVENT_UNLOAD_SUCCEEDED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED); sm_bLoaded = false; sm_bUnloading = false; } else /* if( event_id == CELL_AVC2_EVENT_UNLOAD_FAILED ) */ { INF( "CELL_AVC2_EVENT_UNLOAD_FAILED(0x%x), param(0x%x)\n", event_id, (int)event_param ); setEvent(AVC_EVENT_ERROR); } return ret; } int SonyVoiceChat::eventcb_voiceDetected(CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { UNUSED_VARIABLE( userdata ); // To the upper 32 bits, the room member ID of the player is passed. // In the lower 32 bits, a value of 0 (mute) or a value between 1 (low volume) // and 10 (high volume) is passed as the audio signal value when the notification // method is the level method, or a value of 1 (start of speaking) or 0 (end of speaking) // is stored when the notification method is the trigger method. SceNpMatching2RoomMemberId roomMemberID = (SceNpMatching2RoomMemberId)(event_param >> 32); uint32_t volume = (uint32_t)(event_param & 0xffffffff); // The precision of voice detection is not very high. Since the audio signal values may // always be relatively high depending on the audio input device and the noise level in the // room, you should set a large reference value for determining whether or not a player is // speaking. Relatively good results can be obtained when an audio signal value of at // least 9 is used to determine if a player is speaking. bool bTalking = false; if(volume >= 9) bTalking = true; sm_bTalkingMap[roomMemberID] = bTalking; return CELL_OK; } /* Callback function for handling AV Chat2 Utility events */ void SonyVoiceChat::eventcb( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata) { static struct _cb_func_tbl { CellSysutilAvc2EventId event; int (*func)( CellSysutilAvc2EventId event_id, CellSysutilAvc2EventParam event_param, void *userdata ); } event_tbl[] = { { CELL_AVC2_EVENT_LOAD_SUCCEEDED, eventcb_load }, { CELL_AVC2_EVENT_LOAD_FAILED, eventcb_load }, { CELL_AVC2_EVENT_JOIN_SUCCEEDED, eventcb_join }, { CELL_AVC2_EVENT_JOIN_FAILED, eventcb_join }, { CELL_AVC2_EVENT_LEAVE_SUCCEEDED, eventcb_leave }, { CELL_AVC2_EVENT_LEAVE_FAILED, eventcb_leave }, { CELL_AVC2_EVENT_UNLOAD_SUCCEEDED, eventcb_unload }, { CELL_AVC2_EVENT_UNLOAD_FAILED, eventcb_unload }, { CELL_AVC2_EVENT_SYSTEM_NEW_MEMBER_JOINED, NULL }, { CELL_AVC2_EVENT_SYSTEM_MEMBER_LEFT, NULL }, { CELL_AVC2_EVENT_SYSTEM_SESSION_ESTABLISHED, NULL }, { CELL_AVC2_EVENT_SYSTEM_SESSION_CANNOT_ESTABLISHED,NULL }, { CELL_AVC2_EVENT_SYSTEM_SESSION_DISCONNECTED, NULL }, { CELL_AVC2_EVENT_SYSTEM_VOICE_DETECTED, eventcb_voiceDetected }, }; int ret = 0; for( unsigned int i=0; im_matchingContext, SYS_MEMORY_CONTAINER_ID_INVALID, eventcb, NULL, &g_chat_avc2param ); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2LoadAsync: ret=0x%x\n", ret ); setEvent(AVC_EVENT_ERROR); return ret; } return ret; } int SonyVoiceChat::join() { int ret = CELL_OK; INF("---------------------------------------------------\n"); INF("| cellSysutilAvc2JoinChatRequest \n"); INF("---------------------------------------------------\n"); ret = cellSysutilAvc2JoinChatRequest( &sm_pNetworkManager->m_room ); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2JoinChatRequest: ret=0x%x\n", ret ); setEvent(AVC_EVENT_ERROR); return ret; } return ret; } int SonyVoiceChat::leave() { int ret = CELL_OK; INF("-----------------------------------\n"); INF("| cellSysutilAvc2LeaveChatRequest |\n"); INF("-----------------------------------\n"); ret = cellSysutilAvc2LeaveChatRequest(); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2LeaveChatRequest() = 0x%x\n", ret ); setEvent(AVC_EVENT_ERROR); return ret; } return ret; } int SonyVoiceChat::unload() { int ret = CELL_OK; INF("------------------------------\n"); INF("| cellSysutilAvc2UnloadAsync |\n"); INF("------------------------------\n"); ret = cellSysutilAvc2UnloadAsync(); if( ret != CELL_OK ) { ERR( "cellSysutilAvcUnloadAsync() = 0x%x\n", ret ); setEvent(AVC_EVENT_ERROR); return ret; } sm_bUnloading = true; return ret; } int SonyVoiceChat::start() { sm_bCanStart = (sm_isChatRestricted == false); int ret = CELL_OK; if(sm_bEnabled) ret = startStream(); return ret; } int SonyVoiceChat::stop() { sm_bCanStart = false; int ret = CELL_OK; if(sm_bEnabled) ret = stopStream(); setEvent(AVC_EVENT_CHAT_SESSION_STOPPED); return ret; } int SonyVoiceChat::startStream() { int ret = CELL_OK; INF("---------------------------------\n"); INF("| cellSysutilAvc2StartStreaming |\n"); INF("---------------------------------\n"); ret = cellSysutilAvc2StartStreaming(); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2StartStreaming: ret=0x%x\n", ret ); } ret = cellSysutilAvc2StartVoiceDetection(); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2StartVoiceDetection: ret=0x%x\n", ret ); } return ret; } int SonyVoiceChat::stopStream() { int ret = cellSysutilAvc2StopVoiceDetection(); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2StopVoiceDetection: ret=0x%x\n", ret ); } INF("--------------------------------\n"); INF("| cellSysutilAvc2StopStreaming |\n"); INF("--------------------------------\n"); ret = cellSysutilAvc2StopStreaming(); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2StopStreaming: ret=0x%x\n", ret ); } return ret; } int SonyVoiceChat::initialize(void) { int ret; /* Must use cellSysutilAvc2InitParam() for clearing CellSysutilAvc2InitParam struct*/ ret = cellSysutilAvc2InitParam(CELL_SYSUTIL_AVC2_INIT_PARAM_VERSION, &g_chat_avc2param); if( ret != CELL_OK ) { ERR( "cellSysutilAvc2InitParam failed (0x%x)\n", ret ); return ret; } /* Setting application specific parameters */ g_chat_avc2param.media_type = CELL_SYSUTIL_AVC2_VOICE_CHAT; g_chat_avc2param.max_players = AVC2_PARAM_DEFAULT_MAX_PLAYERS; g_chat_avc2param.voice_param.voice_quality = CELL_SYSUTIL_AVC2_VOICE_QUALITY_NORMAL; g_chat_avc2param.voice_param.max_speakers = AVC2_PARAM_DEFAULT_MAX_SPEAKERS; g_chat_avc2param.spu_load_average = 50; g_chat_avc2param.streaming_mode.mode = CELL_SYSUTIL_AVC2_STREAMING_MODE_NORMAL; setEvent(AVC_EVENT_CHAT_INIT_SUCCEEDED); setState(AVC_STATE_CHAT_INIT); return ret; } int SonyVoiceChat::finalize(void) { setEvent(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED); return CELL_OK; } void SonyVoiceChat::tick() { #ifdef DISABLE_VOICE_CHAT return; #endif static state_transition_table tbl[] = { /* now state event func after the transition state */ { AVC_STATE_CHAT_INIT, AVC_EVENT_EPSILON, initialize, AVC_STATE_CHAT_INIT }, { AVC_STATE_CHAT_INIT, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_INIT, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_INIT, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_INIT, AVC_EVENT_CHAT_INIT_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_LOAD }, { AVC_STATE_CHAT_INIT, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_EPSILON, load, AVC_STATE_CHAT_LOAD }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_CHAT_LOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_JOIN }, { AVC_STATE_CHAT_LOAD, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_EPSILON, join, AVC_STATE_CHAT_JOIN }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_EXIT_GAME, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_LAN_DISCONNECT, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_CHAT_JOIN_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_JOIN, AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EPSILON, start, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_EXIT_GAME, stop, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_ERROR, stop, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_LAN_DISCONNECT, stop, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_CHAT_SESSION_STOPPED, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE }, { AVC_STATE_CHAT_SESSION_PROCESSING,AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT,stop, AVC_STATE_CHAT_SESSION_PROCESSING }, { AVC_STATE_CHAT_LEAVE, AVC_EVENT_EPSILON, leave, AVC_STATE_CHAT_LEAVE }, { AVC_STATE_CHAT_LEAVE, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_LEAVE, AVC_EVENT_CHAT_LEAVE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_EPSILON, unload, AVC_STATE_CHAT_UNLOAD }, { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_UNLOAD, AVC_EVENT_CHAT_UNLOAD_SUCCEEDED, invoke_epsilon_event, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_RESET, AVC_EVENT_EPSILON, finalize, AVC_STATE_CHAT_RESET }, { AVC_STATE_CHAT_RESET, AVC_EVENT_ERROR, invoke_epsilon_event, AVC_STATE_CHAT_LEAVE }, { AVC_STATE_CHAT_RESET, AVC_EVENT_CHAT_FINALIZE_SUCCEEDED, invoke_epsilon_event, AVC_STATE_IDLE }, }; do_state_transition( &tbl[0], sizeof( tbl ) / sizeof( state_transition_table ) ); setBitRate(); } void SonyVoiceChat::do_state_transition( state_transition_table *tbl, int tbl_size ) { int ret = CELL_OK; // if( sm_event == AVC_EVENT_LAN_DISCONNECT || // sm_event == AVC_EVENT_EXIT_GAME || // sm_event == AVC_EVENT_ERROR || // sm_event == AVC_EVENT_FATAL_ERROR ) // { // g_gamedata.finalize = 1; // } // if( sm_event == AVC_EVENT_FATAL_ERROR ) // { // g_gamedata.exit = true; // } bool bCalledFunc = false; for( int i = 0; i < tbl_size; i++ ) { if( sm_state == ( tbl + i )->state ) { if( sm_event == ( tbl + i )->event ) { sm_event = AVC_EVENT_NON; ret = (*( tbl + i )->func)(); bCalledFunc = true; if( ret != CELL_OK ) { ERR("ret = 0x%x\n", ret ); } setState(( tbl + i )->new_state); break; } } } if(bCalledFunc == false) { assert( (sm_event == AVC_EVENT_NON) || (sm_state == AVC_STATE_IDLE && sm_event == AVC_EVENT_EPSILON) ); } } int SonyVoiceChat::invoke_epsilon_event(void) { setEvent(AVC_EVENT_EPSILON); return CELL_OK; } bool SonyVoiceChat::hasMicConnected(const SceNpMatching2RoomMemberId *players_id) { CellSysutilAvc2PlayerInfo players_info; int err = cellSysutilAvc2GetPlayerInfo(players_id, &players_info); if(err == CELL_OK) { if(players_info.connected && players_info.joined) { if(players_info.mic_attached == CELL_AVC2_MIC_STATUS_ATTACHED_ON) return true; } } return false; } void SonyVoiceChat::mute( bool bMute ) { if(sm_bLoaded && !sm_bUnloading) { int err = cellSysutilAvc2SetVoiceMuting(bMute); assert(err == CELL_OK); } } void SonyVoiceChat::mutePlayer( const SceNpMatching2RoomMemberId member_id, bool bMute ) /*Turn chat audio from a specified player on or off */ { if(sm_bLoaded && !sm_bUnloading) { int err = cellSysutilAvc2SetPlayerVoiceMuting(member_id, bMute); assert(err == CELL_OK); } } void SonyVoiceChat::muteLocalPlayer( bool bMute ) /*Turn microphone input on or off */ { if(sm_bLoaded && !sm_bUnloading) { int err = cellSysutilAvc2SetVoiceMuting(bMute); assert(err == CELL_OK); } } bool SonyVoiceChat::isMuted() { if(sm_bLoaded && !sm_bUnloading) { uint8_t bMute; int err = cellSysutilAvc2GetVoiceMuting(&bMute); assert(err == CELL_OK); return bMute; } return false; } bool SonyVoiceChat::isMutedPlayer( const SceNpMatching2RoomMemberId member_id) { if(sm_bLoaded && !sm_bUnloading) { uint8_t bMute; int err = cellSysutilAvc2GetPlayerVoiceMuting(member_id, &bMute); assert(err == CELL_OK); return bMute; } return false; } bool SonyVoiceChat::isMutedLocalPlayer() { if(sm_bLoaded && !sm_bUnloading) { uint8_t bMute; int err = cellSysutilAvc2GetVoiceMuting(&bMute); assert(err == CELL_OK); return bMute; } return false; } void SonyVoiceChat::setVolume( float vol ) { if(sm_bLoaded && !sm_bUnloading) { // The volume level can be set to a value in the range 0.0 to 40.0. // Volume levels are linear values such that if 1.0 is specified, the // volume level will be 1 times the reference power (0dB), and if 0.5 // is specified, the volume level will be 0.5 times the reference power // (-6dB). If 0.0 is specified, chat audio will no longer be audible. int err =cellSysutilAvc2SetSpeakerVolumeLevel(vol * 40.0f); assert(err==CELL_OK); } } float SonyVoiceChat::getVolume() { if(sm_bLoaded && !sm_bUnloading) { float vol; int err = cellSysutilAvc2GetSpeakerVolumeLevel(&vol); assert(err == CELL_OK); return (vol / 40.0f); } return 0; } bool SonyVoiceChat::isTalking( SceNpMatching2RoomMemberId* players_id ) { AUTO_VAR(it, sm_bTalkingMap.find(*players_id)); if (it != sm_bTalkingMap.end() ) return it->second; return false; } void SonyVoiceChat::setBitRate() { if(sm_state != AVC_STATE_CHAT_SESSION_PROCESSING) return; int numPlayers = sm_pNetworkManager->GetPlayerCount(); // This internal attribute represents the maximum voice bit rate. attr_param // is an integer value. The units are bps, and the specifiable values are // 4000, 8000, 16000, 20000, 24000, and 28000. The initial value is 28000. static int bitRates[8] = { 28000, 28000, 28000, 28000, 24000, 20000, 16000, 16000}; int bitRate = bitRates[numPlayers-1]; if(bitRate == sm_currentBitrate) return; CellSysutilAvc2Attribute attr; memset( &attr, 0x00, sizeof(attr) ); attr.attr_id = CELL_SYSUTIL_AVC2_ATTRIBUTE_VOICE_MAX_BITRATE; attr.attr_param.int_param = bitRate; int ret = cellSysutilAvc2SetAttribute(&attr); if( ret == CELL_OK ) { sm_currentBitrate = bitRate; } else { app.DebugPrintf("SonyVoiceChat::setBitRate failed !!! 0x%08x\n", ret); } } #define CASE_STR_VALUE(s) case s: return #s; const char* getStateString(EAVCState state) { switch(state) { CASE_STR_VALUE(AVC_STATE_IDLE); CASE_STR_VALUE(AVC_STATE_CHAT_INIT) CASE_STR_VALUE(AVC_STATE_CHAT_LOAD); CASE_STR_VALUE(AVC_STATE_CHAT_JOIN); CASE_STR_VALUE(AVC_STATE_CHAT_SESSION_PROCESSING); CASE_STR_VALUE(AVC_STATE_CHAT_LEAVE); CASE_STR_VALUE(AVC_STATE_CHAT_RESET); CASE_STR_VALUE(AVC_STATE_CHAT_UNLOAD); CASE_STR_VALUE(AVC_STATE_EXIT); default: return "unknown state"; } } const char* getEventString(EAVCEvent state) { switch(state) { CASE_STR_VALUE(AVC_EVENT_NON); CASE_STR_VALUE(AVC_EVENT_EPSILON); CASE_STR_VALUE(AVC_EVENT_LAN_DISCONNECT); CASE_STR_VALUE(AVC_EVENT_ONLINE); CASE_STR_VALUE(AVC_EVENT_OFFLINE); CASE_STR_VALUE(AVC_EVENT_EXIT_GAME); CASE_STR_VALUE(AVC_EVENT_ROOM_CREATE); CASE_STR_VALUE(AVC_EVENT_ROOM_SEARCH); CASE_STR_VALUE(AVC_EVENT_ERROR); CASE_STR_VALUE(AVC_EVENT_FATAL_ERROR); CASE_STR_VALUE(AVC_EVENT_NETDIALOG_FINISHED); CASE_STR_VALUE(AVC_EVENT_NETDIALOG_UNLOADED); CASE_STR_VALUE(AVC_EVENT_NP2_INIT_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_NP2_FINALIZE_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_NP2_START_CONTEXT_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_NP2_STOP_CONTEXT_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_DESTROY_OR_KICKEDOUT); CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_LEFT); CASE_STR_VALUE(AVC_EVENT_NP2_ROOM_MEMBER_JOINED); CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_LOAD_FAILED); CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_JOIN_FAILED); CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_LEAVE_FAILED); CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_UNLOAD_FAILED); CASE_STR_VALUE(AVC_EVENT_CHAT_INIT_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_FINALIZE_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_CHAT_SESSION_STOPPED); CASE_STR_VALUE(AVC_EVENT_CREATE_JOIN_ROOM_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_SEARCH_ROOM_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_JOIN_ROOM_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_LEAVE_ROOM_SUCCEEDED); CASE_STR_VALUE(AVC_EVENT_SIGNALING_ESTABLISHED); CASE_STR_VALUE(AVC_EVENT_SIGNALING_DEAD); CASE_STR_VALUE(AVC_EVENT_UI_CLOSE_SUCCEEDED); default: return "unknown event"; } } void SonyVoiceChat::printStateAndEvent() { app.DebugPrintf("============== State %20s, Event %20s\n", getStateString(sm_state), getEventString(sm_event)); } void SonyVoiceChat::setEvent( EAVCEvent event ) { sm_event = event; printStateAndEvent(); } void SonyVoiceChat::setState( EAVCState state ) { sm_state = state; printStateAndEvent(); }