33 #define MULTI_VOICE_PRE_DECOMPRESS // when we _are_ using streaming
35 #define MULTI_VOICE_VERBOSE // keep this defined for verbose debug output
37 #define MULTI_VOICE_LOCAL_ECHO // keep this defined for local echo of recorded network voice
46 #define MV_CODE_GIVE_TOKEN 0 // received player side - he now has the token to speak
47 #define MV_CODE_DENY_TOKEN 1 // received player side - server has denied this request
48 #define MV_CODE_TAKE_TOKEN 2 // received player side - the server is forcibly taking his token
49 #define MV_CODE_RELEASE_TOKEN 3 // received server side - player is relinquishing token
50 #define MV_CODE_REQUEST_TOKEN 4 // received server side - player is requesting token
51 #define MV_CODE_PLAYER_PREFS 5 // received server side - player bitflags for who he'll receive from
52 #define MV_CODE_DATA 6 // sound data
53 #define MV_CODE_DATA_DUMMY 7 // in place of a packet which has been deemed too large, so that receivers don't time out early
56 #define MV_DEFAULT_QOS 10 // default quality of sound
60 #define MULTI_VOICE_PRE_SOUND SND_CUE_VOICE
61 #define MULTI_VOICE_POST_SOUND SND_END_VOICE
70 #define MULTI_VOICE_MAX_HEADER_SIZE 22
72 #define MULTI_VOICE_MAX_CHUNK_SIZE 488
75 #define MULTI_VOICE_MAX_BUFFER_SIZE ((1<<16)+(1<<14)) // 80k
78 #define MULTI_VOICE_ACCUM_BUFFER_SIZE (1<<14) // 16k
83 #define MULTI_VOICE_ACCUM_BUFFER_COUNT (MULTI_VOICE_ACCUM_BUFFER_SIZE / MULTI_VOICE_MAX_CHUNK_SIZE)
90 #ifdef MULTI_VOICE_POST_DECOMPRESS
95 #define MULTI_VOICE_MAX_STREAMS 1
99 #define MV_ALG_TIMEOUT 500 // if start get new data for a window then a pause this long, play the window
103 #define MULTI_VOICE_TOKEN_TIMEOUT 7000 // timeout - server will take the token back if he does not hear from the guy in this amount of time
105 #define MULTI_VOICE_TOKEN_RELEASE_WAIT (1.0f) // wait 1 second
108 #define MULTI_VOICE_TOKEN_INDEX_FREE -1 // the token (and the stream are free)
109 #define MULTI_VOICE_TOKEN_INDEX_RELEASED 0xBEAD // the token has been released but the stream is still active
133 #define MULTI_VOICE_KEY KEY_LAPOSTRO // key used for realtime voice
147 #define MULTI_VOICE_DENIED_TIME 1000 // how long to display the "denied" status
256 int idx,s_idx,pre_size,pre_sound;
274 nprintf((
"Network",
"MULTI VOICE : Error initializing rtvoice - recording will not be possible\n"));
281 nprintf((
"Network",
"MULTI VOICE : Error initializing rtvoice - playback will not be possible\n"));
315 nprintf((
"Network",
"MULTI VOICE : Error allocating playback buffer - playback will not be possible\n"));
345 if(Multi_voice_stream[idx].stream_rtvoice_handle == -1){
346 nprintf((
"Network",
"MULTI VOICE : Error getting rtvoice buffer handle - playback will not be possible!\n"));
356 if(Multi_voice_stream[idx].accum_buffer[s_idx] == NULL){
357 nprintf((
"Network",
"MULTI VOICE : Error allocating accum buffer - playback will not be possible\n"));
393 if(Multi_voice_stream[idx].stream_rtvoice_handle != -1){
412 #ifdef MULTI_VOICE_VERBOSE
413 nprintf((
"Network",
"MULTI VOICE : Resetting\n"));
492 if (arg ==
NOX(
"qos")) {
496 dc_printf(
"Quality of sound : %d\n", value);
523 if(Multi_voice_stream[idx].stream_snd_handle != -1){
524 if((earliest == -1) || (Multi_voice_stream[idx].stream_start_time < earliest_time)){
560 switch(Multi_voice_stream[idx].token_status){
568 if(Multi_voice_stream[idx].stream_last_heard == -1){
571 #ifdef MULTI_VOICE_VERBOSE
572 nprintf((
"Network",
"MULTI VOICE : freeing released token (no packets)\n"));
578 t1 =
f2fl(Multi_voice_stream[idx].stream_last_heard);
583 #ifdef MULTI_VOICE_VERBOSE
584 nprintf((
"Network",
"MULTI VOICE : freeing released token (time elapsed)\n"));
593 if((Multi_voice_stream[idx].token_stamp != -1) &&
timestamp_elapsed(Multi_voice_stream[idx].token_stamp)){
621 #ifdef MULTI_VOICE_VERBOSE
622 nprintf((
"Network",
"MULTI VOICE : Request\n"));
632 #ifdef MULTI_VOICE_VERBOSE
640 nprintf((
"Network",
"MULTI VOICE : Error initializing recording!\n"));
671 #ifdef MULTI_VOICE_VERBOSE
672 nprintf((
"Network",
"MULTI VOICE : timestamp popped"));
681 #ifdef MULTI_VOICE_POST_DECOMPRESS
686 #ifdef MULTI_VOICE_LOCAL_ECHO
696 #ifdef MULTI_VOICE_VERBOSE
697 nprintf((
"Network",
"MULTI VOICE : Release\n"));
713 #ifdef MULTI_VOICE_POST_DECOMPRESS
718 #ifdef MULTI_VOICE_LOCAL_ECHO
762 if(Multi_voice_stream[idx].token_status == player_index){
781 Multi_voice_stream[stream_index].
token_status = player_index;
793 #ifdef MULTI_VOICE_VERBOSE
809 ADD_DATA(Multi_voice_stream[stream_index].stream_id);
892 if (stream_index != -1)
949 if(!(pref_flags & (1<<idx))){
972 if((qos > 0) && (qos <= 10)){
973 #ifdef MULTI_VOICE_VERBOSE
974 nprintf((
"Network",
"MULTI VOICE : SETTING QOS %d\n",qos));
992 #ifdef MULTI_VOICE_VERBOSE
993 nprintf((
"Network",
"MULTI VOICE : SETTING MAX RECORD TIME %d\n",duration));
1022 if(
Net_players[player_index].s_info.voice_token_timestamp != -1){
1023 #ifdef MULTI_VOICE_VERBOSE
1024 nprintf((
"Network",
"MULTI VOICE : Not giving token because player %s's timestamp hasn't elapsed yet!\n",
Net_players[player_index].m_player->callsign));
1025 nprintf((
"Network",
"MULTI VOICE : token status %d\n",Multi_voice_stream[0].token_status));
1055 if(Multi_voice_stream[idx].accum_buffer[s_idx] != NULL){
1056 vm_free(Multi_voice_stream[idx].accum_buffer[s_idx]);
1067 ushort chunk_size,uc_size;
1069 int sound_size,size_sent,target_index,max_chunk_size;
1078 gain = (
float)d_gain;
1086 if(target_index == -1){
1102 while(size_sent < sound_size){
1122 uc_size = (
ushort)sound_size;
1129 if((sound_size - size_sent) >= max_chunk_size){
1130 chunk_size = (
ushort)max_chunk_size;
1132 chunk_size = (
ushort)(sound_size - size_sent);
1140 memcpy(data+packet_size, rbuf,chunk_size);
1141 packet_size += chunk_size;
1154 size_sent += (
int)chunk_size;
1162 ubyte stream_id,chunk_index;
1163 ushort chunk_size,uc_size;
1179 offset += chunk_size;
1188 #ifdef MULTI_VOICE_VERBOSE
1189 nprintf((
"Network",
"MULTI VOICE : flushing stream because packet index is too high!!\n"));
1196 offset += chunk_size;
1201 if(stream_index != -1){
1203 Multi_voice_stream[stream_index].
stream_from = who_from;
1206 Multi_voice_stream[stream_index].
stream_id = stream_id;
1223 memcpy(Multi_voice_stream[stream_index].accum_buffer[chunk_index],data+offset,(
int)chunk_size);
1230 if(player_index != -1){
1236 offset += (
int)chunk_size;
1256 #ifdef MULTI_VOICE_VERBOSE
1257 nprintf((
"Network",
"MULTI VOICE : old stream flush\n"));
1271 Multi_voice_stream[stream_index].
token_stamp = -1;
1337 int idx,max_diff_index;
1338 fix cur_time,max_diff;
1342 if(Multi_voice_stream[idx].stream_id == (
ubyte)stream_id){
1349 if(Multi_voice_stream[idx].token_stamp == -1){
1354 #ifdef MULTI_VOICE_VERBOSE
1355 nprintf((
"Network",
"MULTI VOICE : going to blast old voice stream while looking for a free one - beware!!\n"));
1360 max_diff_index = -1;
1363 if(((max_diff_index == -1) || ((cur_time - Multi_voice_stream[idx].stream_last_heard) > max_diff)) && (Multi_voice_stream[idx].token_stamp != -1)){
1364 max_diff_index =
idx;
1370 if(max_diff_index != -1){
1374 return max_diff_index;
1407 if(post_sound == -1){
1414 if(post_sound >= 0){
1416 if(post_sound >= 0){
1417 if(
snd_size(post_sound,&post_size) == -1){
1429 if((max_size - cur_size) > post_size){
1434 cur_size += post_size;
1488 nprintf((
"Network",
"MULTI VOICE : Forcing stream to stop on the record size!!!\n"));
1498 #ifdef MULTI_VOICE_POST_DECOMPRESS
1503 #ifdef MULTI_VOICE_LOCAL_ECHO
1516 str = &Multi_voice_stream[0];
1550 if(target_index == -1){
1618 if(mute_index != -1){
1619 #ifdef MULTI_VOICE_VERBOSE
1639 int player_index,stream_index,target_index;
1685 if(player_index >= 0){
1692 if(player_index >= 0){
1698 if(stream_index >= 0){
1709 Assert(player_index != -1);
1715 #ifdef MULTI_VOICE_VERBOSE
1716 nprintf((
"Network",
"VOICE : PROC DATA\n"));
1724 Assert(target_index != -1);
1737 #ifdef MULTI_VOICE_VERBOSE
1738 nprintf((
"Network",
"VOICE : PROC DATA DUMMY\n"));
1746 Assert(target_index != -1);
1764 ubyte msg_mode,chunk_index;
1765 ushort uc_size,chunk_size;
1766 int max_chunk_size,sent,target_index;
1777 str = &Multi_voice_stream[0];
1787 #ifdef MULTI_VOICE_VERBOSE
1788 nprintf((
"Network",
"MULTI VOICE : streamed packet size too large!!\n"));
1799 #ifdef MULTI_VOICE_VERBOSE
1808 if(target_index == -1){
1843 chunk_index = (
ubyte)sent;
1855 memcpy(data+packet_size, str->
accum_buffer[sent],chunk_size);
1856 packet_size += chunk_size;
1875 int idx,buffer_offset;
1878 #ifdef MULTI_VOICE_VERBOSE
1879 nprintf((
"Network",
"MULTI VOICE : PLAYING STREAM %d\n",stream_index));
1883 st = &Multi_voice_stream[stream_index];
1888 #ifdef MULTI_VOICE_PRE_DECOMPRESS
1902 #ifdef MULTI_VOICE_POST_DECOMPRESS
1920 Assert(Multi_voice_stream[stream_index].stream_rtvoice_handle != -1);
1928 char voice_msg[256];
1929 int player_index =
find_player_id(Multi_voice_stream[stream_index].stream_from);
1931 if(player_index != -1){
1932 memset(voice_msg,0,256);
1957 #ifdef MULTI_VOICE_VERBOSE
1958 nprintf((
"Network",
"MULTI VOICE : DECIDE, TIMEOUT\n"));
1983 player_index =
find_player_id(Multi_voice_stream[idx].stream_from);
1993 nprintf((
"Network",
"Server not playing sound because of set options!\n"));
2025 #define MV_TEST_RECORD_TIME 3000 // recording time in ms for testing voice
2032 unsigned char *outbuf;
2044 nprintf((
"Network",
"Stopping voice test recording\n"));
2121 Assert(Multi_voice_stream[0].stream_snd_handle == -1);
2122 Assert(Multi_voice_stream[0].stream_rtvoice_handle != -1);
void multi_voice_test_record_stop()
int timestamp(int delta_ms)
#define MY_NET_PLAYER_NUM
int multi_voice_alg_should_play(int stream_index)
int rtvoice_init_recording(int qos)
void multi_voice_deny_token(int player_index)
void rtvoice_free_playback_buffer(int index)
#define MULTI_VOICE_STATUS_IDLE
void multi_voice_test_record_start()
struct voice_stream voice_stream
void multi_voice_process_packet(ubyte *data, header *hinfo)
ushort accum_buffer_csize[MULTI_VOICE_ACCUM_BUFFER_COUNT]
#define MULTI_MSG_FRIENDLY
#define MV_CODE_RELEASE_TOKEN
int rtvoice_init_playback()
double accum_buffer_gain[MULTI_VOICE_ACCUM_BUFFER_COUNT]
#define MULTI_VOICE_STATUS_RECORDING
SCP_vector< game_snd > Snds
ushort accum_buffer_usize[MULTI_VOICE_ACCUM_BUFFER_COUNT]
int snd_load(game_snd *gs, int allow_hardware_load)
GLsizei const GLfloat * value
#define PACKET_SET_SIZE()
void multi_voice_process_token_request(int player_index)
#define MV_CODE_DENY_TOKEN
void rtvoice_stop_recording()
void multi_voice_take_token(int stream_index)
int gameseq_get_state(void)
void multi_io_send(net_player *pl, ubyte *data, int len)
int Multi_voice_local_prefs
void multi_voice_set_vars(int qos, int duration)
#define MULTI_VOICE_TOKEN_INDEX_FREE
void multi_voice_player_send_stream()
int multi_voice_test_recording()
void multi_voice_alg_flush_old_stream(int stream_index)
int Multi_voice_pre_sound_size
void rtvoice_get_data(unsigned char **outbuf, int *size, double *gain)
void multi_io_send_reliable(net_player *pl, ubyte *data, int len)
int find_player_id(short player_id)
#define MULTI_VOICE_TOKEN_TIMEOUT
#define MULTI_VOICE_MAX_STREAMS
#define MV_CODE_TAKE_TOKEN
voice_stream Multi_voice_stream[MULTI_VOICE_MAX_STREAMS]
int stream_rtvoice_handle
ubyte Multi_voice_next_stream_id
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
void rtvoice_set_qos(int qos)
char callsign[CALLSIGN_LEN+1]
int Multi_voice_send_mode
void multi_voice_free_all()
int Multi_voice_test_packet_tossed
void multi_voice_process_next_chunk()
int Multi_voice_recording
void multi_voice_process()
#define MULTI_VOICE_TOKEN_RELEASE_WAIT
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
void multi_voice_alg_init()
void multi_display_chat_msg(const char *msg, int player_index, int add_id)
char * Multi_voice_record_buffer
void multi_voice_test_process_next_chunk()
#define MULTI_VOICE_MAX_TIME
#define NETINFO_FLAG_AM_MASTER
void rtvoice_close_recording()
int voice_token_timestamp
multi_server_options options
int Multi_voice_can_record
int snd_get_data(int handle, char *data)
ubyte Multi_voice_stream_id
int multi_voice_process_data(ubyte *data, int player_index, int msg_mode, net_player *target)
#define MV_CODE_DATA_DUMMY
#define MULTI_VOICE_POST_SOUND
int Multi_voice_stamps[MULTI_VOICE_MAX_STREAMS]
int multi_voice_process_data_dummy(ubyte *data)
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define MV_CODE_REQUEST_TOKEN
void multi_voice_maybe_update_vars(int new_qos, int new_duration)
int rtvoice_play(int index, unsigned char *data, int size)
net_player_server_info s_info
#define MV_CODE_GIVE_TOKEN
char * Multi_voice_playback_buffer
void multi_voice_player_process()
int snd_size(int handle, int *size)
void multi_voice_route_data(ubyte *data, int packet_size, int player_index, int mode, net_player *target)
int Multi_voice_current_stream_index
object Objects[MAX_OBJECTS]
#define MLO_FLAG_NO_VOICE
const char * XSTR(const char *str, int index)
#define MULTI_MSG_HOSTILE
void rtvoice_stop_playback(int index)
int Multi_voice_denied_stamp
int Multi_voice_current_stream_sent
#define GM_STANDALONE_SERVER
void rtvoice_uncompress(unsigned char *data_in, int size_in, double gain, unsigned char *data_out, int size_out)
#define MV_TEST_RECORD_TIME
int Multi_voice_player_prefs[MAX_PLAYERS]
int multi_voice_keydown()
void dc_stuff_int(int *i)
Stuffs an int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats...
#define NETINFO_FLAG_CONNECTED
int multi_msg_voice_record()
void multi_voice_request_token()
void dc_stuff_string_white(char *out_str, size_t maxlen)
Stuffs a whitespace delimited string to out_str from the command line, stopping at the end of the com...
void multi_voice_set_prefs(int pref_flags)
void multi_voice_inc_stream_id()
#define MULTI_VOICE_PRE_SOUND
int multi_voice_max_chunk_size(int msg_mode)
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define MSO_FLAG_NO_VOICE
void multi_options_update_netgame()
void multi_voice_alg_play_window(int stream_index)
#define MULTI_VOICE_MAX_BUFFER_SIZE
#define MULTI_CONNECTED(np)
int multi_voice_mix(int post_sound, char *data, int cur_size, int max_size)
fix timer_get_fixed_seconds()
ubyte accum_buffer_flags[MULTI_VOICE_ACCUM_BUFFER_COUNT]
void rtvoice_close_playback()
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
int Multi_voice_test_record_stamp
ubyte keyd_pressed[NUM_KEYS]
#define MULTI_VOICE_STATUS_DENIED
GLenum GLsizei GLenum GLenum const GLvoid * data
int multi_voice_stream_playing(int stream_index)
#define timestamp_elapsed(stamp)
int Multi_voice_recording_stamp
int multi_voice_process_player_prefs(ubyte *data, int player_index)
#define MULTI_VOICE_ACCUM_BUFFER_SIZE
void multi_voice_send_dummy_packet()
void multi_voice_alg_process_streams()
#define MULTI_VOICE_DENIED_TIME
void multi_voice_flush_old_stream(int stream_index)
void multi_voice_give_token(int stream_index, int player_index)
int multi_voice_test_packet_tossed()
int multi_voice_get_stream(int stream_id)
void dc_printf(const char *format,...)
Prints the given char string to the debug console.
int rtvoice_create_playback_buffer()
void multi_voice_client_send_pending()
#define MULTI_VOICE_TOKEN_INDEX_RELEASED
void rtvoice_stop_playback_all()
void multi_voice_server_process()
int rtvoice_start_recording(void(*user_callback)(), int callback_time)
void multi_voice_release_token()
#define MULTI_VOICE_STATUS_PLAYING
int multi_find_player_by_object(object *objp)
void multi_voice_alg_process_data(int stream_index)
net_player Net_players[MAX_PLAYERS]
int multi_voice_find_token(int player_index)
#define MULTI_VOICE_ACCUM_BUFFER_COUNT
multi_global_options Multi_options_g
void multi_voice_test_process()
int multi_find_player_by_net_signature(ushort net_signature)
ubyte * accum_buffer[MULTI_VOICE_ACCUM_BUFFER_COUNT]
multi_local_options options
int multi_voice_test_get_playback_buffer()
#define MV_CODE_PLAYER_PREFS