FS2_Open
Open source remastering of the Freespace 2 engine
multi_voice.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "network/multi_voice.h"
14 #include "io/timer.h"
15 #include "io/key.h"
17 #include "network/multimsgs.h"
18 #include "network/multiutil.h"
19 #include "network/multi_pmsg.h"
20 #include "gamesnd/gamesnd.h"
21 #include "sound/rtvoice.h"
23 #include "network/multi.h"
24 #include "playerman/player.h"
25 #include "debugconsole/console.h"
26 
27 
28 // --------------------------------------------------------------------------------------------------
29 // MULTI VOICE DEFINES/VARS
30 //
31 
32 // #define MULTI_VOICE_POST_DECOMPRESS // when we're _not_ using streaming
33 #define MULTI_VOICE_PRE_DECOMPRESS // when we _are_ using streaming
34 
35 #define MULTI_VOICE_VERBOSE // keep this defined for verbose debug output
36 
37 #define MULTI_VOICE_LOCAL_ECHO // keep this defined for local echo of recorded network voice
38 
39 // flag indicating the status of the multi voice system
43 int Multi_voice_send_mode = MULTI_MSG_NONE; // gotten from the multi_msg system when we start recording
44 
45 // packet code defines
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
54 
55 // default quality of sound
56 #define MV_DEFAULT_QOS 10 // default quality of sound
57 int Multi_voice_qos; // default quality of sound
58 
59 // sounds added to the front and end of a playing voice stream (set to -1 if none are wanted)
60 #define MULTI_VOICE_PRE_SOUND SND_CUE_VOICE
61 #define MULTI_VOICE_POST_SOUND SND_END_VOICE
63 
64 // sound data
65 
66 // NOTE : the following 2 defines should be used for reference only. they represent the worst case situation,
67 // sending voice to a specific target under IPX. you should use multi_voice_max_chunk_size(...) when
68 // determining if a given chunk will fit into an individual freespace packet
69 // max size of a data packet header (note, this changes as the code itself changes - should probably never use this except for reference)
70 #define MULTI_VOICE_MAX_HEADER_SIZE 22
71 // size of an individual chunk (CHUNK == block of data stuck into a packet), in the worst case of header size (see above)
72 #define MULTI_VOICE_MAX_CHUNK_SIZE 488
73 
74 // total max size of an incoming or an outgoing uncompressed buffer (note this is probably too big, but we won't worry about that for now)
75 #define MULTI_VOICE_MAX_BUFFER_SIZE ((1<<16)+(1<<14)) // 80k
76 
77 // overall size of an total accum buffer for a stream
78 #define MULTI_VOICE_ACCUM_BUFFER_SIZE (1<<14) // 16k
79 
80 // how many accum buffers need to be in a total accum buffer
81 // NOTE : we reference MULTI_VOICE_MAX_CHUNK_SIZE here because it is worst case. ie, we'll always have enough
82 // accum buffers in anything better than the worst case if we use MULTI_VOICE_MAX_CHUNK_SIZE
83 #define MULTI_VOICE_ACCUM_BUFFER_COUNT (MULTI_VOICE_ACCUM_BUFFER_SIZE / MULTI_VOICE_MAX_CHUNK_SIZE)
84 
85 int Multi_voice_max_time; // current maximum recording time
86 char *Multi_voice_record_buffer = NULL; // buffer for recording back voice
87 char *Multi_voice_playback_buffer = NULL; // buffer for processing the accum buffer and playing the result
88 
89 // DEBUG CODE
90 #ifdef MULTI_VOICE_POST_DECOMPRESS
91  char Multi_voice_unpack_buffer[MULTI_VOICE_MAX_BUFFER_SIZE];
92 #endif
93 
94 // the max amount of tokens we want to be floating about (max sound streams)
95 #define MULTI_VOICE_MAX_STREAMS 1
96 
97 // voice algorithm stuff
98 // it would probably be good to base the timeout time on some multiple of our average ping to the server
99 #define MV_ALG_TIMEOUT 500 // if start get new data for a window then a pause this long, play the window
101 
102 // NOTE : this should be > then MULTI_VOICE_MAX_TIME + the time for the data to come over a network connection!!
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
104 
105 #define MULTI_VOICE_TOKEN_RELEASE_WAIT (1.0f) // wait 1 second
106 
107 // the token index of a voice stream is set to one of these values, or the index of the player who has the token
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
110 
111 typedef struct voice_stream {
112  int token_status; // status of the token (player index if a player has it) or one of the above defines
113  int token_stamp; // timestamp for the MULTI_VOICE_TOKEN_TIMEOUT
114 
115  short stream_from; // id of the player the stream is coming from
116 
118  ubyte accum_buffer_flags[MULTI_VOICE_ACCUM_BUFFER_COUNT]; // flag indicating the existence of a given accum (sub)buffer
119  ushort accum_buffer_usize[MULTI_VOICE_ACCUM_BUFFER_COUNT]; // uncompressed size of the corresponding (sub)buffer
120  ushort accum_buffer_csize[MULTI_VOICE_ACCUM_BUFFER_COUNT]; // compressed size of the corresponding (sub)buffer
121  double accum_buffer_gain[MULTI_VOICE_ACCUM_BUFFER_COUNT]; // gain of the corresponding (sub)buffer
122 
123  ubyte stream_id; // stream id #
124  fix stream_last_heard; // last time we heard from this stream
125 
126  fix stream_start_time; // time the stream started playing
127  int stream_snd_handle; // sound playing instance handle
128  int stream_rtvoice_handle; // rtvoice buffer handle
129 } voice_stream;
131 
132 // player-side data
133 #define MULTI_VOICE_KEY KEY_LAPOSTRO // key used for realtime voice
134 int Multi_voice_keydown = 0; // is the record key currently being pressed
135 int Multi_voice_recording = 0; // flag indicating if we're currently recording or not
136 int Multi_voice_token = 0; // if we currently have a token or not
137 int Multi_voice_recording_stamp = -1; // how long we've been recording
138 ubyte Multi_voice_stream_id = 0; // stream id for the stream we're currently sending
139 int Multi_voice_current_stream_index = 0; // packet index of the currently recodring stream
140 int Multi_voice_current_stream_sent = -1; // index of packet we've sent up to
141 
142 // server-side data
143 ubyte Multi_voice_next_stream_id = 0; // kept on the server - given to the next valid token requester
144 int Multi_voice_player_prefs[MAX_PLAYERS]; // player bitflag preferences
145 
146 // voice status data - used for determing the result of multi_voice_status
147 #define MULTI_VOICE_DENIED_TIME 1000 // how long to display the "denied" status
148 int Multi_voice_denied_stamp = -1; // timestamp for when we got denied a token
149 
150 // local muting preferences
151 int Multi_voice_local_prefs = 0xffffffff;
152 
153 
154 // --------------------------------------------------------------------------------------------------
155 // MULTI VOICE FORWARD DECLARATIONS
156 //
157 
158 // process voice details as the server
160 
161 // process voice details as a player (may also be the server)
163 
164 // determine if the voice key is down this frame
165 int multi_voice_keydown();
166 
167 // find the voice stream index by token player index
168 int multi_voice_find_token(int player_index);
169 
170 // <server> gives the token to a given player
171 void multi_voice_give_token(int stream_index,int player_index);
172 
173 // <server> takes the token from a given stream entry
174 void multi_voice_take_token(int stream_index);
175 
176 // <server> tells the client he's been denied on this request
177 void multi_voice_deny_token(int player_index);
178 
179 // <player> releases the token back to the server
181 
182 // <player> requests the token from the server
184 
185 // <server> process a request for the token
186 void multi_voice_process_token_request(int player_index);
187 
188 // free up any memory which may have been malloced
189 void multi_voice_free_all();
190 
191 // <player> send the currently recorded sound
193 
194 // process incoming sound data, return bytes processed
195 int multi_voice_process_data(ubyte *data, int player_index,int msg_mode,net_player *target);
196 
197 // <server> increment the current stream id#
199 
200 // flush any old sound stream data because we've started to receive data for a new stream
201 void multi_voice_flush_old_stream(int stream_index);
202 
203 // route sound data through the server to all appropriate players
204 void multi_voice_route_data(ubyte *data, int packet_size,int player_index,int mode,net_player *target);
205 
206 // find the stream to apply incoming sound data to, freeing up old ones as necessary
207 int multi_voice_get_stream(int stream_id);
208 
209 // NOTE : these 4 functions can be arbitrarily written to perform in any way necessary. This way the algorithm is
210 // completely seperate from the transport and token layers
211 // initialize the smart algorithm
212 void multi_voice_alg_init();
213 
214 // process incoming sound data in whatever way necessary (this function should take care of playing data when necessary)
215 void multi_voice_alg_process_data(int stream_index);
216 
217 // process existing streams
219 
220 // we are going to flush the current stream because we have started to receive data for a new one. do something first
221 void multi_voice_alg_flush_old_stream(int stream_index);
222 
223 // is the given sound stream playing (compares uncompressed sound size with current playback position)
224 int multi_voice_stream_playing(int stream_index);
225 
226 // tack on a post voice sound (pass -1 for none)
227 // return final buffer size
228 int multi_voice_mix(int post_sound,char *data,int cur_size,int max_size);
229 
230 // send a dummy packet in the place of a too-large data packet
232 
233 // process a dummy data packet
235 
236 // max size of a sound chunk which we can fit into a packet
237 int multi_voice_max_chunk_size(int msg_mode);
238 
239 // process a player preferences packet, return bytes processed
240 int multi_voice_process_player_prefs(ubyte *data,int player_index);
241 
242 // process and play the current window of sound stream data we have. reset the window for the next incoming data as well
243 void multi_voice_alg_play_window(int stream_index);
244 
245 // send all pending voice packets
247 
248 
249 // --------------------------------------------------------------------------------------------------
250 // MULTI VOICE FUNCTIONS
251 //
252 
253 // initialize the multiplayer voice system
255 {
256  int idx,s_idx,pre_size,pre_sound;
257 
258  // if the voice system is already initialized, just reset some stuff
259  if(Multi_voice_inited){
261  return;
262  }
263 
264  // set the default quality of sound
266 
267  // if we're the standalone server, we can't record _or_ playback, but we can still route data and manage tokens
271  } else {
272  // initialize the realtime voice module
274  nprintf(("Network","MULTI VOICE : Error initializing rtvoice - recording will not be possible\n"));
276  } else {
278  }
279 
280  if(rtvoice_init_playback()){
281  nprintf(("Network","MULTI VOICE : Error initializing rtvoice - playback will not be possible\n"));
283  } else {
285  }
286 
287  // _always_ set the quality of server
289  }
290 
291  // initialize player-side data
292  Multi_voice_token = 0;
299 
300  // initialize server-side data
301  memset(Multi_voice_player_prefs,0xff,sizeof(int)*MAX_PLAYERS);
303 
304  Multi_voice_local_prefs = 0xffffffff;
305 
306  // initialize the sound buffers
308 
312  // attempt to allocate the buffer
314  if(Multi_voice_playback_buffer == NULL){
315  nprintf(("Network","MULTI VOICE : Error allocating playback buffer - playback will not be possible\n"));
317  }
318 
319  // attempt to copy in the "pre" voice sound
320  pre_sound = snd_load(&Snds[MULTI_VOICE_PRE_SOUND], 0);
321  if(pre_sound != -1){
322  // get the pre-sound size
323  if((snd_size(pre_sound,&pre_size) != -1) && (pre_size < MULTI_VOICE_MAX_BUFFER_SIZE)){
325  Multi_voice_pre_sound_size = pre_size;
326  } else {
328  }
329  } else {
331  }
332  }
333 
334  // initialize the streams
335  memset(Multi_voice_stream,0,sizeof(voice_stream) * MULTI_VOICE_MAX_STREAMS);
336  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
337  Multi_voice_stream[idx].token_status = MULTI_VOICE_TOKEN_INDEX_FREE;
338  Multi_voice_stream[idx].token_stamp = -1;
339  Multi_voice_stream[idx].stream_snd_handle = -1;
340 
341  // get a playback buffer handle
343  Multi_voice_stream[idx].stream_rtvoice_handle = -1;
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"));
348 
350  }
351 
352  // allocate the accum buffer
353  for(s_idx=0;s_idx<MULTI_VOICE_ACCUM_BUFFER_COUNT;s_idx++){
354  Multi_voice_stream[idx].accum_buffer[s_idx] = NULL;
355  Multi_voice_stream[idx].accum_buffer[s_idx] = (ubyte*)vm_malloc(MULTI_VOICE_ACCUM_BUFFER_SIZE);
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"));
359 
361  }
362  }
363  }
364  }
365 
366  // initialize the default max time
368 
369  // initialize voice status data
371 
372  // initialize the smart algorithm
374 
375  Multi_voice_inited = 1;
376 }
377 
378 // shutdown the multiplayer voice system
380 {
381  int idx;
382 
383  // if the voice system isn't already initialized, don't do anything
384  if(!Multi_voice_inited){
385  return;
386  }
387 
388  // free up buffers
390 
391  // release all the rtvoice buffers
392  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
393  if(Multi_voice_stream[idx].stream_rtvoice_handle != -1){
394  rtvoice_free_playback_buffer(Multi_voice_stream[idx].stream_rtvoice_handle);
395  Multi_voice_stream[idx].stream_rtvoice_handle = -1;
396  Multi_voice_stream[idx].stream_snd_handle = -1;
397  }
398  }
399 
400  // close the realtime voice module
403 
404  Multi_voice_inited = 0;
405 }
406 
407 // reset between levels
409 {
410  int idx;
411 
412 #ifdef MULTI_VOICE_VERBOSE
413  nprintf(("Network","MULTI VOICE : Resetting\n"));
414 #endif
415 
417 
418  // if we're the standalone server, we can't record _or_ playback, but we can still route data and manage tokens
422  }
423 
424  // initialize player-side data
425  Multi_voice_token = 0;
430 
431  // initialize server-side data
432  memset(Multi_voice_player_prefs,0xff,sizeof(int)*MAX_PLAYERS);
433  Multi_voice_local_prefs = 0xffffffff;
435 
436  // initialize the sound buffers
438 
439  // initialize the streams
440  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
441  Multi_voice_stream[idx].token_status = MULTI_VOICE_TOKEN_INDEX_FREE;
442  Multi_voice_stream[idx].token_stamp = -1;
443  }
444 
445  // initialize the smart algorithm
447 }
448 
449 // process all voice details
451 {
452  int idx;
453 
454  // don't do anything if the voice module is not initialized
456  return;
457  }
458 
459  // send all pending voice packets
461 
462  // find any playing sound streams which have finished and unmark them
463  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
464  if((Multi_voice_stream[idx].stream_snd_handle != -1) && !multi_voice_stream_playing(idx)){
465  Multi_voice_stream[idx].stream_snd_handle = -1;
466  }
467  }
468 
469  // process seperately as player or server
472  }
473 
474  // all "players" do this, except the standalone who isn't a real player by definition
477  }
478 
479  // everyont calls the general algorithm process function
481 }
482 
483 // voice settings debug console function
485 {
486  SCP_string arg;
487  int value;
488 
490 
491  // set the quality of sound
492  if (arg == NOX("qos")) {
493  dc_stuff_int(&value);
494  if((value >= 1) && (value <= 10) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
495  multi_voice_set_vars(value,-1);
496  dc_printf("Quality of sound : %d\n", value);
497  }
498  }
499 }
500 
501 // the status of the voice system - use this to determine what bitmaps to display, etc see above MULTI_VOICE_STATUS_* defines
503 {
504  int idx;
505  int earliest;
506  fix earliest_time;
507 
508  // if the "denied" timestamp is set, return that as the status
509  if(Multi_voice_denied_stamp != -1){
511  }
512 
513  // if we're currently recording (has precedence over playing back a sound from somebody)
516  }
517 
518  // find the stream which started playing the farthest back (if any)
519  earliest = -1;
520  earliest_time = -1;
521  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
522  // if we found a playing stream
523  if(Multi_voice_stream[idx].stream_snd_handle != -1){
524  if((earliest == -1) || (Multi_voice_stream[idx].stream_start_time < earliest_time)){
525  earliest = idx;
526  earliest_time = Multi_voice_stream[idx].stream_start_time;
527  }
528  }
529  }
530  // if we found a stream
531  if(earliest != -1){
533  }
534 
535  // system is idle
537 }
538 
539 // update the qos if the current setting is different from the passed in value
540 void multi_voice_maybe_update_vars(int new_qos,int new_duration)
541 {
542  // if the current qos is different from the passed qos, set it
543  if((new_qos != Multi_voice_qos) || (new_duration != Multi_voice_max_time)){
544  multi_voice_set_vars(new_qos,new_duration);
545  }
546 }
547 
548 
549 // --------------------------------------------------------------------------------------------------
550 // MULTI VOICE FORWARD DECLARATIONS
551 //
552 
553 // process voice details as the server
555 {
556  int idx;
557 
558  // process all the tokens for all the available streams
559  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
560  switch(Multi_voice_stream[idx].token_status){
561  // if the token is free, so is the stream - don't do anything
563  break;
564 
565  // if the token has been released - check to see if the stream is "done" (ie, can be marked as FREE once again)
567  // if the stream_last_heard var is -1, it means we never got sound from this guy so free the token up immediately
568  if(Multi_voice_stream[idx].stream_last_heard == -1){
569  Multi_voice_stream[idx].token_status = MULTI_VOICE_TOKEN_INDEX_FREE;
570 
571 #ifdef MULTI_VOICE_VERBOSE
572  nprintf(("Network","MULTI VOICE : freeing released token (no packets)\n"));
573 #endif
574  }
575  // if a sufficiently long amount of time has elapsed since he released the token, free it up
576  else {
577  float t1,t2;
578  t1 = f2fl(Multi_voice_stream[idx].stream_last_heard);
580  if((t2 - t1) >= MULTI_VOICE_TOKEN_RELEASE_WAIT){
581  Multi_voice_stream[idx].token_status = MULTI_VOICE_TOKEN_INDEX_FREE;
582 
583 #ifdef MULTI_VOICE_VERBOSE
584  nprintf(("Network","MULTI VOICE : freeing released token (time elapsed)\n"));
585 #endif
586  }
587  }
588  break;
589 
590  // if the token is still being held by a player
591  default :
592  // if the token timestamp has elapsed, take the token back
593  if((Multi_voice_stream[idx].token_stamp != -1) && timestamp_elapsed(Multi_voice_stream[idx].token_stamp)){
594  Assert(Multi_voice_stream[idx].token_status != MULTI_VOICE_TOKEN_INDEX_FREE);
596  }
597  break;
598  }
599  }
600 
601  // for each netplayer, if his token wait timestamp is running, see if it has popped yet
602  for(idx=0;idx<MAX_PLAYERS;idx++){
603  if(MULTI_CONNECTED(Net_players[idx]) && (Net_players[idx].s_info.voice_token_timestamp != -1) && timestamp_elapsed(Net_players[idx].s_info.voice_token_timestamp)){
604  // unset it so that he can have the token again
606  }
607  }
608 }
609 
610 // process voice details as a player (may also be the server)
612 {
613  // if the voice key is down for the first time this frame, send a request for the token
615  // mark the key as being down
617 
618  // send a request for a token
620 
621 #ifdef MULTI_VOICE_VERBOSE
622  nprintf(("Network","MULTI VOICE : Request\n"));
623 #endif
624  }
625 
626  // if the key is still being pressed
628  // if we have the token
629  if(Multi_voice_token){
630  // if we're not already recording, start recording
632 #ifdef MULTI_VOICE_VERBOSE
633  nprintf(("Network","MULTI VOICE : RECORD %d\n",(int)Multi_voice_stream_id));
634 #endif
635  // flush the old stream
637 
638  // start the recording process with the appropriate callback function
640  nprintf(("Network","MULTI VOICE : Error initializing recording!\n"));
641  return;
642  }
643 
644  // set myself to be recording
646 
647  // set the time when I started recording
649 
650  // set the current packet/chunk index to 0
653 
654  // get the proper messaging mode
655  if(Game_mode & GM_IN_MISSION){
656  // in mission, paused
659  }
660  // in mission, unpaused
661  else {
663  }
664  } else {
666  }
667  }
668 
669  // if we've recorded the max time allowed, send the data
671 #ifdef MULTI_VOICE_VERBOSE
672  nprintf(("Network","MULTI VOICE : timestamp popped"));
673 #endif
674  // mark me as no longer recording
677 
678  // stop the recording process
680 
681 #ifdef MULTI_VOICE_POST_DECOMPRESS
683 #endif
684 
685  // play my sound locally as well
686 #ifdef MULTI_VOICE_LOCAL_ECHO
688 #endif
689  // release the token back to the server
691  }
692  }
693  }
694  // if the key has been released
696 #ifdef MULTI_VOICE_VERBOSE
697  nprintf(("Network","MULTI VOICE : Release\n"));
698 #endif
699 
700  // mark the kay as not being down
702 
703  // if we were recording, send the data
705  // mark me as no longer recording
707 
709 
710  // stop the recording process
712 
713 #ifdef MULTI_VOICE_POST_DECOMPRESS
715 #endif
716 
717  // play my sound locally as well
718 #ifdef MULTI_VOICE_LOCAL_ECHO
720 #endif
721 
722  // release the token back to the server
724  }
725  }
726 
727  // if the "denied" timestamp is set, but has elapsed or the user has let up on the key, set it to -1
730  }
731 }
732 
733 // determine if the voice key is down this frame
735 {
736  // if we're in the options screen, we should never allow the button to be pressed
738  return 0;
739  }
740 
741  // if we're pre-game, we should just be checking the keyboard bitflags
742  if(!(Game_mode & GM_IN_MISSION)){
744  }
745 
746  // in-mission, paused - treat just like any other "chattable" screen.
749  }
750 
751  // ingame, unpaused, rely on the multi-messaging system (ingame)
752  return multi_msg_voice_record();
753 }
754 
755 // find the voice stream index by token player index
756 int multi_voice_find_token(int player_index)
757 {
758  int idx;
759 
760  // look through all the existing streams
761  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
762  if(Multi_voice_stream[idx].token_status == player_index){
763  return idx;
764  }
765  }
766 
767  // couldn't find it
768  return -1;
769 }
770 
771 // <server> gives the token to a given player
772 void multi_voice_give_token(int stream_index,int player_index)
773 {
774  ubyte data[10],code;
775  int packet_size = 0;
776 
777  // only the server should ever be here
779 
780  // set this player as having the token
781  Multi_voice_stream[stream_index].token_status = player_index;
782 
783  // set the token timeout
784  Multi_voice_stream[stream_index].token_stamp = timestamp(MULTI_VOICE_TOKEN_TIMEOUT);
785 
786  // set the stream id and increment the count
787  Multi_voice_stream[stream_index].stream_id = Multi_voice_next_stream_id;
789 
790  // set the last heard from time to -1 to indicate we've heard no sound from this guy
791  Multi_voice_stream[stream_index].stream_last_heard = -1;
792 
793 #ifdef MULTI_VOICE_VERBOSE
794  nprintf(("Network","MULTI VOICE : GIVE TOKEN %d\n",(int)Multi_voice_next_stream_id));
795 #endif
796 
797  // if we're giving to ourself, don't send any data
798  if(Net_player == &Net_players[player_index]){
799  Multi_voice_token = 1;
800 
801  Multi_voice_stream_id = Multi_voice_stream[stream_index].stream_id;
802  } else {
803  // send the "give" packet to the guy
805  code = MV_CODE_GIVE_TOKEN;
806  ADD_DATA(code);
807 
808  // add the current stream id#
809  ADD_DATA(Multi_voice_stream[stream_index].stream_id);
810 
811  // send reliably
812  multi_io_send_reliable(&Net_players[player_index], data, packet_size);
813  }
814 }
815 
816 // <server> takes the token from a given player
817 void multi_voice_take_token(int stream_index)
818 {
819  ubyte data[10],code;
820  int packet_size = 0;
821 
822  // only the server should ever be here
824 
825  // if the index is -1, the token has probably been released to us "officially" already
826  if((Multi_voice_stream[stream_index].token_status == (int)MULTI_VOICE_TOKEN_INDEX_FREE) || (Multi_voice_stream[stream_index].token_status == (int)MULTI_VOICE_TOKEN_INDEX_RELEASED)){
827  Multi_voice_stream[stream_index].token_stamp = -1;
828  return;
829  }
830 
831  // if i'm taking from myself, don't send any data
832  if(Net_player == &Net_players[Multi_voice_stream[stream_index].token_status]){
833  Multi_voice_token = 0;
834 
835  // timestamp this guy so that he can't get the token back immediately
837  } else {
838  // send the "take" packet to the guy
840  code = MV_CODE_TAKE_TOKEN;
841  ADD_DATA(code);
842 
843  // send reliably
844  multi_io_send_reliable(&Net_players[Multi_voice_stream[stream_index].token_status], data, packet_size);
845 
846  // timestamp this guy so that he can't get the token back immediately
848  }
849 
850  // take the token back from the dude
851  Multi_voice_stream[stream_index].token_status = MULTI_VOICE_TOKEN_INDEX_RELEASED;
852  Multi_voice_stream[stream_index].token_stamp = -1;
853 }
854 
855 // <server> tells the client he's been denied on this request
856 void multi_voice_deny_token(int player_index)
857 {
858  ubyte data[10],code;
859  int packet_size = 0;
860 
861  // only the server should ever be here
863 
864 
865  // if i'm denying myself, set the denied timestamp
866  if(Net_player == &Net_players[player_index]){
868  } else {
869  // send the "deny" packet to the guy
871  code = MV_CODE_DENY_TOKEN;
872  ADD_DATA(code);
873 
874  // send reliably
875  multi_io_send_reliable(&Net_players[player_index], data, packet_size);
876  }
877 }
878 
879 // <player> releases the token back to the server
881 {
882  ubyte data[10],code;
883  int packet_size = 0;
884 
885  // I don't have the token anymore
886  Multi_voice_token = 0;
887 
888  // if i'm the server, don't send any data
890  // mark the token as being released
891  int stream_index = multi_voice_find_token(MY_NET_PLAYER_NUM);
892  if (stream_index != -1)
893  Multi_voice_stream[stream_index].token_status = MULTI_VOICE_TOKEN_INDEX_RELEASED;
894 
895  // timestamp this guy so that he can't get the token back immediately
897  } else {
898  // send the "release" packet to the server
900  code = MV_CODE_RELEASE_TOKEN;
901  ADD_DATA(code);
902 
903  // send reliably
904  multi_io_send_reliable(Net_player, data, packet_size);
905  }
906 }
907 
908 // <player> requests the token from the server
910 {
911  ubyte data[10],code;
912  int packet_size = 0;
913 
914  // if i'm the server, process the request right now
917  } else {
918  // send the "request" packet to the server
920  code = MV_CODE_REQUEST_TOKEN;
921  ADD_DATA(code);
922 
923  // send reliably
924  multi_io_send_reliable(Net_player, data, packet_size);
925  }
926 }
927 
928 // <player> sends hit bitflag settings (who he'll receive sound from, etc)
929 void multi_voice_set_prefs(int pref_flags)
930 {
932  int idx;
933  int packet_size = 0;
934 
935  // set the local flags
936  Multi_voice_local_prefs = pref_flags;
937 
938  // if i'm the server, set the sound prefs right now
941  } else {
942  // send the prefs to the server
944  code = MV_CODE_PLAYER_PREFS;
945  ADD_DATA(code);
946 
947  // add the address of all players being ignored
948  for(idx=0;idx<MAX_PLAYERS;idx++){
949  if(!(pref_flags & (1<<idx))){
950  code = 0x0;
951  ADD_DATA(code);
952 
953  // add the player's id
954  ADD_SHORT(Net_players[idx].player_id);
955  }
956  }
957  // add final stop byte
958  code = 0xff;
959  ADD_DATA(code);
960 
961  // send reliably
962  multi_io_send_reliable(Net_player, data, packet_size);
963  }
964 }
965 
966 // set the default voice quality and duration (if server passes -1, he just broadcasts the qos to all clients)
967 void multi_voice_set_vars(int qos,int duration)
968 {
969  int need_update = 0;
970 
971  // make sure its in the right range
972  if((qos > 0) && (qos <= 10)){
973 #ifdef MULTI_VOICE_VERBOSE
974  nprintf(("Network","MULTI VOICE : SETTING QOS %d\n",qos));
975 #endif
976 
977  // set the default value
978  Multi_voice_qos = qos;
979 
980  // set the value in the rtvoice module
982 
983  // update the netgame settings
986  need_update = 1;
987  }
988  }
989 
990  // set the maximum duration
991  if((duration > 0) && (duration <= MULTI_VOICE_MAX_TIME)){
992 #ifdef MULTI_VOICE_VERBOSE
993  nprintf(("Network","MULTI VOICE : SETTING MAX RECORD TIME %d\n",duration));
994 #endif
995  // set the default value
996  Multi_voice_max_time = duration;
997 
998  // update the netgame settings
1000  Netgame.options.voice_record_time = duration;
1001  need_update = 1;
1002  }
1003  }
1004 
1005  // send an options update if necessary
1006  if(need_update && !(Game_mode & GM_STANDALONE_SERVER)){
1008  }
1009 }
1010 
1011 // <server> process a request for the token
1013 {
1014  int idx;
1015 
1016  // if we're not doing voice on this server, return now
1018  return;
1019  }
1020 
1021  // if the player's token timestamp is not -1, can't give him the token
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));
1026 #endif
1027  // deny the guy
1028  multi_voice_deny_token(player_index);
1029  return;
1030  }
1031 
1032  // attempt to find a free token token
1033  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
1034  if(Multi_voice_stream[idx].token_status == MULTI_VOICE_TOKEN_INDEX_FREE){
1035  multi_voice_give_token(idx,player_index);
1036  return;
1037  }
1038  }
1039 }
1040 
1041 // free up any memory which may have been malloced
1043 {
1044  int idx,s_idx;
1045 
1046  // free up the playback buffer
1047  if(Multi_voice_playback_buffer != NULL){
1050  }
1051 
1052  // free up the accum buffers
1053  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
1054  for(s_idx=0;s_idx<MULTI_VOICE_ACCUM_BUFFER_COUNT;s_idx++){
1055  if(Multi_voice_stream[idx].accum_buffer[s_idx] != NULL){
1056  vm_free(Multi_voice_stream[idx].accum_buffer[s_idx]);
1057  Multi_voice_stream[idx].accum_buffer[s_idx] = NULL;
1058  }
1059  }
1060  }
1061 }
1062 
1063 // <player> send the currently recorded sound
1065 {
1066  ubyte data[MAX_PACKET_SIZE],code,*rbuf,msg_mode,chunk_index;
1067  ushort chunk_size,uc_size;
1068  int packet_size = 0;
1069  int sound_size,size_sent,target_index,max_chunk_size;
1070  float gain;
1071  double d_gain;
1072 
1073  // we'd better not ever get here as we can't record voice
1075 
1076  // get the data
1077  rtvoice_get_data((unsigned char**)&Multi_voice_record_buffer, &sound_size, &d_gain);
1078  gain = (float)d_gain;
1079 
1080  msg_mode = (ubyte)Multi_voice_send_mode;
1081  // get the specific target if we're in MSG_TARGET mode
1082  target_index = -1;
1083  if(msg_mode == MULTI_MSG_TARGET){
1084  if(Player_ai->target_objnum != -1){
1086  if(target_index == -1){
1087  return;
1088  }
1089  } else {
1090  return;
1091  }
1092  }
1093 
1094  // get the max chunk size
1096 
1097  // go through the data and send all of it
1098  code = MV_CODE_DATA;
1099  chunk_index = 0;
1100  size_sent = 0;
1101  rbuf = (unsigned char*)Multi_voice_record_buffer;
1102  while(size_sent < sound_size){
1103  // build the header and add the opcode
1105 
1106  // add the packet code type
1107  ADD_DATA(code);
1108 
1109  // add the routing data and any necessary targeting information
1110  ADD_DATA(msg_mode);
1111  if(msg_mode == MULTI_MSG_TARGET){
1112  ADD_DATA(Objects[Net_players[target_index].m_player->objnum].net_signature);
1113  }
1114 
1115  // add my id#
1117 
1118  // add the current stream id#
1120 
1121  Assert(sound_size < MULTI_VOICE_MAX_BUFFER_SIZE);
1122  uc_size = (ushort)sound_size;
1123  ADD_USHORT(uc_size);
1124 
1125  // add the chunk index
1126  ADD_DATA(chunk_index);
1127 
1128  // determine how much we are going to send in this packet
1129  if((sound_size - size_sent) >= max_chunk_size){
1130  chunk_size = (ushort)max_chunk_size;
1131  } else {
1132  chunk_size = (ushort)(sound_size - size_sent);
1133  }
1134  ADD_USHORT(chunk_size);
1135 
1136  // add the gain
1137  ADD_FLOAT(gain);
1138 
1139  // add the chunk of data
1140  memcpy(data+packet_size, rbuf,chunk_size);
1141  packet_size += chunk_size;
1142 
1143  // send to the server or rebroadcast if I _am_ the server
1145  multi_voice_route_data(data,packet_size,MY_NET_PLAYER_NUM,(int)msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1146  } else {
1147  multi_io_send(Net_player, data, packet_size);
1148  }
1149 
1150  // increment the chunk_index
1151  chunk_index++;
1152 
1153  // increment bytes sent and the buffer
1154  size_sent += (int)chunk_size;
1155  rbuf += chunk_size;
1156  }
1157 }
1158 
1159 // process incoming sound data, return bytes processed
1160 int multi_voice_process_data(ubyte *data, int player_index,int msg_mode,net_player *target)
1161 {
1162  ubyte stream_id,chunk_index;
1163  ushort chunk_size,uc_size;
1164  short who_from;
1165  int stream_index;
1166  float gain;
1167  int offset = 0;
1168 
1169  // read in all packet data except for the sound chunk itself
1170  GET_SHORT(who_from);
1171  GET_DATA(stream_id);
1172  GET_USHORT(uc_size);
1173  GET_DATA(chunk_index);
1174  GET_USHORT(chunk_size);
1175  GET_FLOAT(gain);
1176 
1177  // if our netgame options are currently set for no voice, ignore the packet
1179  offset += chunk_size;
1180  return offset;
1181  }
1182 
1183  // get a handle to a valid stream to be using, freeing old streams as necessary
1184  stream_index = multi_voice_get_stream((int)stream_id);
1185 
1186  // if this index is too high, flush the stream
1187  if(chunk_index >= MULTI_VOICE_ACCUM_BUFFER_COUNT){
1188 #ifdef MULTI_VOICE_VERBOSE
1189  nprintf(("Network","MULTI VOICE : flushing stream because packet index is too high!!\n"));
1190 #endif
1191 
1192  // flush the stream
1193  multi_voice_flush_old_stream(stream_index);
1194 
1195  // return bytes processed
1196  offset += chunk_size;
1197  return offset;
1198  }
1199 
1200  // if we found a stream to work with
1201  if(stream_index != -1){
1202  // set the id of where it came from
1203  Multi_voice_stream[stream_index].stream_from = who_from;
1204 
1205  // set the stream id#
1206  Multi_voice_stream[stream_index].stream_id = stream_id;
1207 
1208  // set the gain
1209  Multi_voice_stream[stream_index].accum_buffer_gain[chunk_index] = (double)gain;
1210 
1211  // set the stream uncompressed size size
1212  Multi_voice_stream[stream_index].accum_buffer_usize[chunk_index] = uc_size;
1213 
1214  // set the token timestamp
1215  Multi_voice_stream[stream_index].token_stamp = timestamp(MULTI_VOICE_TOKEN_TIMEOUT);
1216 
1217  // set the last heard time
1218  Multi_voice_stream[stream_index].stream_last_heard = timer_get_fixed_seconds();
1219 
1220  // copy the data and setup any other accum buffer data necessary
1221  // ignore data if we can't play sounds
1223  memcpy(Multi_voice_stream[stream_index].accum_buffer[chunk_index],data+offset,(int)chunk_size);
1224  }
1225 
1226  Multi_voice_stream[stream_index].accum_buffer_flags[chunk_index] = 1;
1227  Multi_voice_stream[stream_index].accum_buffer_csize[chunk_index] = chunk_size;
1228 
1229  // pass the data into the smart voice algorithm
1230  if(player_index != -1){
1231  multi_voice_alg_process_data(stream_index);
1232  }
1233  }
1234 
1235  // increment the offset
1236  offset += (int)chunk_size;
1237 
1238  return offset;
1239 }
1240 
1241 // <server> increment the current stream id#
1243 {
1245 
1246  if(Multi_voice_next_stream_id == 0xff){
1248  } else {
1250  }
1251 }
1252 
1253 // flush any old sound stream data because we've started to receive data for a new stream
1254 void multi_voice_flush_old_stream(int stream_index)
1255 {
1256 #ifdef MULTI_VOICE_VERBOSE
1257  nprintf(("Network","MULTI VOICE : old stream flush\n"));
1258 #endif
1259 
1260  // call the smart algorithm for flushing streams
1261  multi_voice_alg_flush_old_stream(stream_index);
1262 
1263  // clear all the accum buffer flags
1264  memset(Multi_voice_stream[stream_index].accum_buffer_flags,0,MULTI_VOICE_ACCUM_BUFFER_COUNT);
1265 
1266  // clear the token
1268  multi_voice_take_token(stream_index);
1269  }
1270 
1271  Multi_voice_stream[stream_index].token_stamp = -1;
1272  Multi_voice_stream[stream_index].token_status = MULTI_VOICE_TOKEN_INDEX_FREE;
1273 
1274  // timestamp the player
1276 }
1277 
1278 // route sound data through the server to all appropriate players
1280 {
1281  int idx;
1282 
1283  // route the data to all other players
1284  switch(mode){
1285  case MULTI_MSG_ALL:
1286  for(idx=0;idx<MAX_PLAYERS;idx++){
1287  if(MULTI_CONNECTED( Net_players[idx] ) && // player is connected
1288  ( &Net_players[idx] != &Net_players[player_index] ) && // not the sending player
1289  ( Net_player != &Net_players[idx] ) && // not me
1290  ( Multi_voice_player_prefs[idx] & (1 << player_index) ) && // is accepting sound from this player
1291  !( Net_players[idx].p_info.options.flags & MLO_FLAG_NO_VOICE ) ){ // is accepting sound periods
1292 
1293  multi_io_send(&Net_players[idx], data, packet_size);
1294  }
1295  }
1296  break;
1297 
1298  case MULTI_MSG_FRIENDLY:
1299  for(idx=0;idx<MAX_PLAYERS;idx++){
1300  if(MULTI_CONNECTED( Net_players[idx] ) && // player is connected
1301  ( &Net_players[idx] != &Net_players[player_index] ) && // not the sending player
1302  ( Net_player != &Net_players[idx] ) && // not me
1303  ( Net_players[idx].p_info.team == Net_players[player_index].p_info.team ) &&// on the same team
1304  ( Multi_voice_player_prefs[idx] & (1 << player_index) ) && // is accepting sound from the sender
1305  !( Net_players[idx].p_info.options.flags & MLO_FLAG_NO_VOICE) ){ // is accepting sound periods
1306 
1307  multi_io_send(&Net_players[idx], data, packet_size);
1308  }
1309  }
1310  break;
1311  case MULTI_MSG_HOSTILE:
1312  for(idx=0;idx<MAX_PLAYERS;idx++){
1313  if(MULTI_CONNECTED( Net_players[idx] ) && // player is connected
1314  ( &Net_players[idx] != &Net_players[player_index] ) && // not the sending player
1315  ( Net_player != &Net_players[idx] ) && // not me
1316  ( Net_players[idx].p_info.team != Net_players[player_index].p_info.team ) &&// on the opposite team
1317  ( Multi_voice_player_prefs[idx] & (1 << player_index) ) && // is accepting sound from the sender
1318  !( Net_players[idx].p_info.options.flags & MLO_FLAG_NO_VOICE ) ){ // is accepting sound periods
1319 
1320  multi_io_send(&Net_players[idx], data, packet_size);
1321  }
1322  }
1323  break;
1324 
1325  case MULTI_MSG_TARGET:
1326  Assert(target != NULL);
1327  if(!(target->p_info.options.flags & MLO_FLAG_NO_VOICE)){
1328  multi_io_send(target, data, packet_size);
1329  }
1330  break;
1331  }
1332 }
1333 
1334 // find the stream to apply incoming sound data to, freeing up old ones as necessary
1335 int multi_voice_get_stream(int stream_id)
1336 {
1337  int idx,max_diff_index;
1338  fix cur_time,max_diff;
1339 
1340  // first check to see if this stream exists
1341  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
1342  if(Multi_voice_stream[idx].stream_id == (ubyte)stream_id){
1343  return idx;
1344  }
1345  }
1346 
1347  // if we got to this point, we didn't find the matching stream, so we should try and find an empty stream
1348  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
1349  if(Multi_voice_stream[idx].token_stamp == -1){
1350  return idx;
1351  }
1352  }
1353 
1354 #ifdef MULTI_VOICE_VERBOSE
1355  nprintf(("Network","MULTI VOICE : going to blast old voice stream while looking for a free one - beware!!\n"));
1356 #endif
1357 
1358  // if we got to this point, we should free up the oldest stream we have
1359  cur_time = timer_get_fixed_seconds();
1360  max_diff_index = -1;
1361  max_diff = -1;
1362  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
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;
1365  max_diff = cur_time - Multi_voice_stream[idx].stream_last_heard;
1366  }
1367  }
1368 
1369  // if we found the oldest
1370  if(max_diff_index != -1){
1371  // flush the old stream
1372  multi_voice_flush_old_stream(max_diff_index);
1373 
1374  return max_diff_index;
1375  }
1376 
1377  // some other fail condition
1378  return -1;
1379 }
1380 
1381 // is the given sound stream playing (compares uncompressed sound size with current playback position)
1382 int multi_voice_stream_playing(int stream_index)
1383 {
1384  // if the handle is invalid, it can't be playing
1385  /*
1386  if(Multi_voice_stream[stream_index].stream_snd_handle < 0){
1387  return 0;
1388  }
1389 
1390  // if the sound is playing and the buffer is past the uncompressed size, its effectively done
1391  if(ds_get_play_position(ds_get_channel(Multi_voice_stream[stream_index].stream_snd_handle)) >= (DWORD)Multi_voice_stream[stream_index].stream_uc_size){
1392  return 1;
1393  }
1394  */
1395 
1396  // not done yet
1397  return 0;
1398 }
1399 
1400 // tack on pre and post sounds to a sound stream (pass -1 for either if no sound is wanted)
1401 // return final buffer size
1402 int multi_voice_mix(int post_sound,char *data,int cur_size,int max_size)
1403 {
1404  int post_size;
1405 
1406  // if the user passed -1 for both pre and post sounds, don't do a thing
1407  if(post_sound == -1){
1408  return cur_size;
1409  }
1410 
1411  // get the sizes of the additional sounds
1412 
1413  // post sound
1414  if(post_sound >= 0){
1415  post_sound = snd_load(&Snds[post_sound], 0);
1416  if(post_sound >= 0){
1417  if(snd_size(post_sound,&post_size) == -1){
1418  post_size = 0;
1419  }
1420  } else {
1421  post_size = 0;
1422  }
1423  } else {
1424  post_size = 0;
1425  }
1426 
1427  // if we have a "post" sound to add
1428  if(post_size > 0){
1429  if((max_size - cur_size) > post_size){
1430  // copy in the sound
1431  snd_get_data(post_sound,data + cur_size);
1432 
1433  // increment the cur_size
1434  cur_size += post_size;
1435  }
1436  }
1437 
1438  // return the size of the new buffer
1439  return cur_size;
1440 }
1441 
1442 // max size of a sound chunk which we can fit into a packet
1444 {
1445  int header_size;
1446 
1447  // all headers contain the following data
1448  header_size = 1 + // messaging mode
1449  1 + // stream id #
1450  2 + // packet uncompressed size
1451  2 + // compressed size
1452  4; // gain
1453 
1454  // if we're targeting a specific player
1455  if(msg_mode == MULTI_MSG_TARGET){
1456  header_size += 2; // targeted player's object net_signature
1457  }
1458 
1459  // allocate header space for my address
1460  header_size += 4; // my address (4 bytes in TCP)
1461 
1462  // calculate max chunk size
1463  return (MAX_PACKET_SIZE - // max freespace packet size
1464  1 - // packet type
1465  1 - // voice packet code subtype
1466  header_size); // calculated header size
1467 }
1468 
1469 // --------------------------------------------------------------------------------------------------
1470 // MULTI VOICE / RTVOICE INTERFACE
1471 //
1472 
1473 // process the "next" chunk of standalone valid sound data from the rtvoice system
1475 {
1476  int sound_size;
1477  double d_gain;
1478  voice_stream *str;
1479 
1480  // we'd better not ever get here is we can't record voice
1482 
1483  // get the data
1484  rtvoice_get_data((unsigned char**)&Multi_voice_record_buffer, &sound_size, &d_gain);
1485 
1486  // if we've reached the max # of packets for this stream, bail
1488  nprintf(("Network","MULTI VOICE : Forcing stream to stop on the record size!!!\n"));
1489 
1490  // mark me as no longer recording
1491  Multi_voice_recording = 0;
1492 
1494 
1495  // stop the recording process
1497 
1498 #ifdef MULTI_VOICE_POST_DECOMPRESS
1500 #endif
1501 
1502  // play my sound locally as well
1503 #ifdef MULTI_VOICE_LOCAL_ECHO
1505 #endif
1506  // release the token back to the server
1508 
1509  // unset the timestamp so we don't still think we're still recording
1511 
1512  return;
1513  }
1514 
1515  // pack the data locally as well (so I can hear myself)
1516  str = &Multi_voice_stream[0];
1518  str->stream_from = Net_player->player_id;
1523 
1524  // increment the stream index
1526 }
1527 
1528 
1529 // --------------------------------------------------------------------------------------------------
1530 // MULTI VOICE PACKET HANDLERS
1531 //
1532 
1533 // send a dummy packet in the place of a too-large data packet
1535 {
1536  ubyte data[10],code,msg_mode;
1537  int packet_size,target_index;
1538 
1539  // build the header and add the opcode
1541  code = (ubyte)MV_CODE_DATA_DUMMY;
1542  ADD_DATA(code);
1543 
1544  msg_mode = (ubyte)Multi_voice_send_mode;
1545  // get the specific target if we're in MSG_TARGET mode
1546  target_index = -1;
1547  if(msg_mode == MULTI_MSG_TARGET){
1548  if(Player_ai->target_objnum != -1){
1550  if(target_index == -1){
1551  return;
1552  }
1553  } else {
1554  return;
1555  }
1556  }
1557  ADD_DATA(msg_mode);
1558  if(msg_mode == MULTI_MSG_TARGET){
1559  ADD_USHORT(Objects[Net_players[target_index].m_player->objnum].net_signature);
1560  }
1561 
1562  // add the voice stream id
1564 
1565  // send to the server or rebroadcast if I _am_ the server
1567  multi_voice_route_data(data,packet_size,MY_NET_PLAYER_NUM,(int)msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1568  } else {
1569  multi_io_send(Net_player, data, packet_size);
1570  }
1571 }
1572 
1573 // process a dummy data packet
1575 {
1576  int offset = 0;
1577  int stream_index;
1578  ubyte stream_id;
1579 
1580  // get the stream id
1581  GET_DATA(stream_id);
1582 
1583  // get the proper stream index
1584  if ( (stream_index = multi_voice_get_stream((int)stream_id) ) != -1 ) {
1585 
1586  // set the token timestamp
1587  Multi_voice_stream[stream_index].token_stamp = timestamp(MULTI_VOICE_TOKEN_TIMEOUT);
1588 
1589  // set the last heard time
1590  Multi_voice_stream[stream_index].stream_last_heard = timer_get_fixed_seconds();
1591 
1592  // set the timeout timestamp
1593  Multi_voice_stamps[stream_index] = timestamp(MV_ALG_TIMEOUT);
1594  }
1595 
1596  // return bytes processed
1597  return offset;
1598 }
1599 
1600 // process a player preferences packet, return bytes processed
1602 {
1603  ubyte val;
1604  int mute_index;
1605  short mute_id;
1606  int offset = 0;
1607 
1608  // set all channels active
1609  Multi_voice_player_prefs[player_index] = 0xffffffff;
1610 
1611  // get all muted players
1612  GET_DATA(val);
1613  while(val != 0xff){
1614  GET_SHORT(mute_id);
1615 
1616  // get the player to mute
1617  mute_index = find_player_id(mute_id);
1618  if(mute_index != -1){
1619 #ifdef MULTI_VOICE_VERBOSE
1620  nprintf(("Network","Player %s muting player %s\n",Net_players[player_index].m_player->callsign,Net_players[mute_index].m_player->callsign));
1621 #endif
1622  // mute the guy
1623  Multi_voice_player_prefs[player_index] &= ~(1<<mute_index);
1624  }
1625 
1626  // get the next stop value
1627  GET_DATA(val);
1628  }
1629 
1630  // return bytes processed
1631  return offset;
1632 }
1633 
1634 // process an incoming voice packet of some kind or another
1636 {
1637  ubyte code,msg_mode;
1638  ushort target_sig;
1639  int player_index,stream_index,target_index;
1640  int offset = HEADER_LENGTH;
1641 
1642  // find out who is sending this data
1643  player_index = find_player_id(hinfo->id);
1644 
1645  // get the opcode
1646  GET_DATA(code);
1647 
1648  // process the packet
1649  switch(code){
1650  // I don't have the token anymore
1651  case MV_CODE_TAKE_TOKEN:
1652  // we should never have the token if we cannot record
1654  Int3();
1655  }
1656 
1657  Multi_voice_token = 0;
1658  break;
1659 
1660  // I have been denied the token
1661  case MV_CODE_DENY_TOKEN:
1662  // set the "denied" timestamp
1664  break;
1665 
1666  // I now have the token
1667  case MV_CODE_GIVE_TOKEN:
1669 
1670  // we should never get the token if we cannot record
1672  Int3();
1673  }
1674 
1675  // if we no longer have the keydown, automatically release the token
1676  if(!Multi_voice_keydown){
1678  } else {
1679  Multi_voice_token = 1;
1680  }
1681  break;
1682 
1683  // a request for the token from a player
1684  case MV_CODE_REQUEST_TOKEN:
1685  if(player_index >= 0){
1686  multi_voice_process_token_request(player_index);
1687  }
1688  break;
1689 
1690  // a player gave up the token
1691  case MV_CODE_RELEASE_TOKEN:
1692  if(player_index >= 0){
1693  stream_index = multi_voice_find_token(player_index);
1694  } else {
1695  break;
1696  }
1697 
1698  if(stream_index >= 0){
1699  // set the token as having been released
1700  Multi_voice_stream[stream_index].token_status = MULTI_VOICE_TOKEN_INDEX_RELEASED;
1701 
1702  // timestamp this guy so that he can't get the token back immediately
1704  }
1705  break;
1706 
1707  // a player has set prefs for himself
1708  case MV_CODE_PLAYER_PREFS:
1709  Assert(player_index != -1);
1710  offset += multi_voice_process_player_prefs(data+offset,player_index);
1711  break;
1712 
1713  // a data packet
1714  case MV_CODE_DATA:
1715 #ifdef MULTI_VOICE_VERBOSE
1716  nprintf(("Network","VOICE : PROC DATA\n"));
1717 #endif
1718  // get routing information
1719  target_index = -1;
1720  GET_DATA(msg_mode);
1721  if(msg_mode == MULTI_MSG_TARGET){
1722  GET_USHORT(target_sig);
1723  target_index = multi_find_player_by_net_signature(target_sig);
1724  Assert(target_index != -1);
1725  }
1726 
1727  offset += multi_voice_process_data(data+offset,player_index,msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1728 
1729  // if we're the server of the game, we should also route this data to all other players
1731  multi_voice_route_data(data,offset,player_index,msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1732  }
1733  break;
1734 
1735  // a data dummy packet
1736  case MV_CODE_DATA_DUMMY:
1737 #ifdef MULTI_VOICE_VERBOSE
1738  nprintf(("Network","VOICE : PROC DATA DUMMY\n"));
1739 #endif
1740  // get routing information
1741  target_index = -1;
1742  GET_DATA(msg_mode);
1743  if(msg_mode == MULTI_MSG_TARGET){
1744  GET_USHORT(target_sig);
1745  target_index = multi_find_player_by_net_signature(target_sig);
1746  Assert(target_index != -1);
1747  }
1748 
1749  offset += multi_voice_process_data_dummy(data+offset);
1750 
1751  // if we're the server of the game, we should also route this data to all other players
1753  multi_voice_route_data(data,offset,player_index,msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1754  }
1755  break;
1756  }
1757  PACKET_SET_SIZE();
1758 }
1759 
1760 // send all pending voice packets
1762 {
1764  ubyte msg_mode,chunk_index;
1765  ushort uc_size,chunk_size;
1766  int max_chunk_size,sent,target_index;
1767  int packet_size;
1768  float gain;
1769  voice_stream *str;
1770 
1771  // if we're not recording
1773  return;
1774  }
1775 
1776  // stream all buffered up packets
1777  str = &Multi_voice_stream[0];
1780 
1781  // get the current messaging mode
1782  msg_mode = (ubyte)Multi_voice_send_mode;
1783 
1784  // if the size of this voice chunk will fit in the packet
1786  if(str->accum_buffer_csize[sent] > max_chunk_size){
1787 #ifdef MULTI_VOICE_VERBOSE
1788  nprintf(("Network","MULTI VOICE : streamed packet size too large!!\n"));
1789 #endif
1790 
1792 
1793  // send a dummy data packet instead
1795 
1796  continue;
1797  }
1798 
1799 #ifdef MULTI_VOICE_VERBOSE
1800  nprintf(("Network","MULTI VOICE : PACKET %d %d\n",(int)str->accum_buffer_csize[sent],(int)str->accum_buffer_usize[sent]));
1801 #endif
1802 
1803  // get the specific target if we're in MSG_TARGET mode
1804  target_index = -1;
1805  if(msg_mode == MULTI_MSG_TARGET){
1806  if(Player_ai->target_objnum != -1){
1808  if(target_index == -1){
1809  return;
1810  }
1811  } else {
1812  return;
1813  }
1814  }
1815 
1816  // go through the data and send all of it
1817  code = MV_CODE_DATA;
1818  chunk_index = 0;
1819 
1820  // if this packet is small enough to fit within a psnet data packet
1822 
1823  // add the packet code type
1824  ADD_DATA(code);
1825 
1826  // add the routing data and any necessary targeting information
1827  ADD_DATA(msg_mode);
1828  if(msg_mode == MULTI_MSG_TARGET){
1830  ADD_USHORT(Objects[Net_players[target_index].m_player->objnum].net_signature);
1831  }
1832 
1833  // add my address
1835 
1836  // add the current stream id#
1838 
1839  uc_size = (ushort)str->accum_buffer_usize[sent];
1840  ADD_USHORT(uc_size);
1841 
1842  // add the chunk index
1843  chunk_index = (ubyte)sent;
1844  ADD_DATA(chunk_index);
1845 
1846  // size of the sound data
1847  chunk_size = (ushort)str->accum_buffer_csize[sent];
1848  ADD_USHORT(chunk_size);
1849 
1850  // add the gain
1851  gain = (float)str->accum_buffer_gain[sent];
1852  ADD_FLOAT(gain);
1853 
1854  // add the chunk of data
1855  memcpy(data+packet_size, str->accum_buffer[sent],chunk_size);
1856  packet_size += chunk_size;
1857 
1858  // send to the server or rebroadcast if I _am_ the server
1860  multi_voice_route_data(data,packet_size,MY_NET_PLAYER_NUM,(int)msg_mode,(target_index == -1) ? NULL : &Net_players[target_index]);
1861  } else {
1862  multi_io_send(Net_player, data, packet_size);
1863  }
1864  }
1865 }
1866 
1867 
1868 // --------------------------------------------------------------------------------------------------
1869 // MULTI VOICE ALGORITHM stuff
1870 //
1871 
1872 // process and play the current window of sound stream data we have. reset the window for the next incoming data as well
1873 void multi_voice_alg_play_window(int stream_index)
1874 {
1875  int idx,buffer_offset;
1876  voice_stream *st;
1877 
1878 #ifdef MULTI_VOICE_VERBOSE
1879  nprintf(("Network","MULTI VOICE : PLAYING STREAM %d\n",stream_index));
1880 #endif
1881 
1882  // get a pointer to the stream
1883  st = &Multi_voice_stream[stream_index];
1884 
1885  // don't play anything back if we can't hear sound
1886  if(Multi_voice_can_play){
1887  // first, pack all the accum buffers into the playback buffer
1888 #ifdef MULTI_VOICE_PRE_DECOMPRESS
1889  buffer_offset = Multi_voice_pre_sound_size;
1890  nprintf(("Network","VOICE : pre sound size %d\n",Multi_voice_pre_sound_size));
1891  for(idx=0;idx<MULTI_VOICE_ACCUM_BUFFER_COUNT;idx++){
1892  // if the flag is set, uncompress the data into the playback buffer
1893  if(st->accum_buffer_flags[idx]){
1894  // first, uncompress the data
1896 
1897  // increment the buffer offset
1898  buffer_offset += st->accum_buffer_usize[idx];
1899  }
1900  }
1901 #endif
1902 #ifdef MULTI_VOICE_POST_DECOMPRESS
1903  buffer_offset = 0;
1904  for(idx=0;idx<MULTI_VOICE_ACCUM_BUFFER_COUNT;idx++){
1905  // if the flag is set, copy the data
1906  if(st->accum_buffer_flags[idx]){
1907  memcpy(Multi_voice_unpack_buffer+buffer_offset,st->accum_buffer[idx],st->accum_buffer_csize[idx]);
1908  buffer_offset += st->accum_buffer_csize[idx];
1909  }
1910  }
1911 
1912  // decompress the whole shebang
1913  rtvoice_uncompress((ubyte*)Multi_voice_unpack_buffer,buffer_offset,st->accum_buffer_gain[0],(ubyte*)Multi_voice_playback_buffer,st->accum_buffer_usize[0]);
1914  buffer_offset = st->accum_buffer_usize[0];
1915 #endif
1916 
1917  // mix in the SND_CUE_VOICE and the SND_END_VOICE game sounds
1919 
1920  Assert(Multi_voice_stream[stream_index].stream_rtvoice_handle != -1);
1921 
1922  // kill any previously playing sounds
1923  rtvoice_stop_playback(Multi_voice_stream[stream_index].stream_rtvoice_handle);
1924  Multi_voice_stream[stream_index].stream_snd_handle = -1;
1925 
1926  // if we can play sound and we know who this is from, display it
1928  char voice_msg[256];
1929  int player_index = find_player_id(Multi_voice_stream[stream_index].stream_from);
1930 
1931  if(player_index != -1){
1932  memset(voice_msg,0,256);
1933  sprintf(voice_msg,XSTR("<%s is speaking>",712),Net_players[player_index].m_player->callsign);
1934 
1935  // display a chat message (write to the correct spot - hud, standalone gui, chatbox, etc)
1936  multi_display_chat_msg(voice_msg,player_index,0);
1937  }
1938  }
1939 
1940  // now call the rtvoice playback functions
1941  Multi_voice_stream[stream_index].stream_snd_handle = rtvoice_play(Multi_voice_stream[stream_index].stream_rtvoice_handle,(unsigned char*)Multi_voice_playback_buffer,buffer_offset);
1942  Multi_voice_stream[stream_index].stream_start_time = timer_get_fixed_seconds();
1943  }
1944 
1945  // unset the stamp so that its not "free"
1946  Multi_voice_stamps[stream_index] = -1;
1947 
1948  // flush the stream (will also grab the token back, if the server)
1949  multi_voice_flush_old_stream(stream_index);
1950 }
1951 
1952 // decision function which decides if we should play the current block of sound we have
1953 int multi_voice_alg_should_play(int stream_index)
1954 {
1955  // if the timestamp has expired, play the sound
1956  if((Multi_voice_stamps[stream_index] != -1) && timestamp_elapsed(Multi_voice_stamps[stream_index])){
1957 #ifdef MULTI_VOICE_VERBOSE
1958  nprintf(("Network","MULTI VOICE : DECIDE, TIMEOUT\n"));
1959 #endif
1960  return 1;
1961  }
1962 
1963  return 0;
1964 }
1965 
1966 // process incoming sound data in whatever way necessary (this function should take care of playing data when necessary)
1967 void multi_voice_alg_process_data(int stream_index)
1968 {
1969  // update the timestamp for this window
1970  Multi_voice_stamps[stream_index] = timestamp(MV_ALG_TIMEOUT);
1971 }
1972 
1973 // process existing streams
1975 {
1976  int idx;
1977  int player_index;
1978 
1979  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
1980  // determine if we should play this window of data
1981  if((Multi_voice_stamps[idx] != -1) && multi_voice_alg_should_play(idx)){
1982  // determine who this stream came from
1983  player_index = find_player_id(Multi_voice_stream[idx].stream_from);
1984 
1985  // server should check his own settings here
1986  if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && ((Net_player->p_info.options.flags & MLO_FLAG_NO_VOICE) || (player_index == -1) || !(Multi_voice_player_prefs[MY_NET_PLAYER_NUM] & (1<<player_index))) ){
1987  // unset the stamp so that its not "free"
1988  Multi_voice_stamps[idx] = -1;
1989 
1990  // flush the stream (will also grab the token back, if the server)
1992 
1993  nprintf(("Network","Server not playing sound because of set options!\n"));
1994  }
1995  // play the current sound
1996  else {
1998  }
1999  }
2000  }
2001 }
2002 
2003 // we are going to flush the current stream because we have started to receive data for a new one. do something first
2004 void multi_voice_alg_flush_old_stream(int stream_index)
2005 {
2006  // just unset the heard from timestamp for now
2007  Multi_voice_stamps[stream_index] = -1;
2008 }
2009 
2010 // initialize the smart algorithm
2012 {
2013  int idx;
2014 
2015  for(idx=0;idx<MULTI_VOICE_MAX_STREAMS;idx++){
2016  Multi_voice_stamps[idx] = -1;
2017  }
2018 }
2019 
2020 
2021 // --------------------------------------------------------------------------------------------------
2022 // MULTI VOICE TESTING FUNCTIONS
2023 //
2024 
2025 #define MV_TEST_RECORD_TIME 3000 // recording time in ms for testing voice
2028 
2029 // process the next chunk of voice data
2031 {
2032  unsigned char *outbuf;
2033  int size;
2034  double gain;
2035 
2036  // if the test recording stamp is -1, we should stop
2039  return;
2040  }
2041 
2042  // if the recording timestamp has elapsed, stop the whole thing
2044  nprintf(("Network","Stopping voice test recording\n"));
2045 
2047 
2050  return;
2051  }
2052 
2053  // otherwise get the compressed and uncompressed data and do something interesting with it
2054  rtvoice_get_data(&outbuf, &size, &gain);
2055 
2056  // determine whether the packet would have been dropped
2059  } else {
2061  }
2062 
2063  // send the raw output buffer to the voice options screen
2064  options_multi_set_voice_data(outbuf, size, gain);
2065 }
2066 
2067 // start recording voice locally for playback testing
2069 {
2070  // if there is test recording going on already, don't do anything
2072  return;
2073  }
2074 
2075  // stop any playback which may be occuring
2077 
2078  // stop any recording which may be occuring
2080 
2081  // set the timestamp
2083 
2084  // start the recording of voice
2086 }
2087 
2088 // force stop any recording voice test
2090 {
2094 }
2095 
2096 // return if the test recording is going on
2098 {
2099  return (Multi_voice_test_record_stamp == -1) ? 0 : 1;
2100 }
2101 
2102 // call this function if multi_voice_test_recording() is true to process various odds and ends of the test recording
2104 {
2105  // if we're not recording, do nothing
2107  return;
2108  }
2109 
2110  // check to see if the timestamp has elapsed
2114  }
2115 }
2116 
2117 // get a playback buffer handle (return -1 if none exist - bad)
2119 {
2120  // return voice stream 0
2121  Assert(Multi_voice_stream[0].stream_snd_handle == -1);
2122  Assert(Multi_voice_stream[0].stream_rtvoice_handle != -1);
2123 
2124  return Multi_voice_stream[0].stream_rtvoice_handle;
2125 }
2126 
2127 // return whether the last sampled chunk would have been too large to fit in a packet
2129 {
2131 }
void multi_voice_test_record_stop()
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
#define vm_free(ptr)
Definition: pstypes.h:548
int multi_voice_alg_should_play(int stream_index)
#define GET_DATA(d)
Definition: multimsgs.h:47
int rtvoice_init_recording(int qos)
Definition: rtvoice.cpp:149
void multi_voice_deny_token(int player_index)
void rtvoice_free_playback_buffer(int index)
Definition: rtvoice.cpp:420
ai_info * Player_ai
Definition: ai.cpp:24
#define MULTI_VOICE_STATUS_IDLE
Definition: multi_voice.h:22
void multi_voice_test_record_start()
struct voice_stream voice_stream
int Game_mode
Definition: systemvars.cpp:24
void multi_voice_process_packet(ubyte *data, header *hinfo)
ushort accum_buffer_csize[MULTI_VOICE_ACCUM_BUFFER_COUNT]
#define MULTI_MSG_FRIENDLY
Definition: multi_pmsg.h:28
#define MV_CODE_RELEASE_TOKEN
Definition: multi_voice.cpp:49
int rtvoice_init_playback()
Definition: rtvoice.cpp:332
double accum_buffer_gain[MULTI_VOICE_ACCUM_BUFFER_COUNT]
#define MULTI_VOICE_STATUS_RECORDING
Definition: multi_voice.h:24
net_player * Net_player
Definition: multi.cpp:94
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
ushort accum_buffer_usize[MULTI_VOICE_ACCUM_BUFFER_COUNT]
int snd_load(game_snd *gs, int allow_hardware_load)
Definition: sound.cpp:281
GLsizei const GLfloat * value
Definition: Glext.h:5646
#define PACKET_SET_SIZE()
Definition: multimsgs.h:57
void multi_voice_process_token_request(int player_index)
player * m_player
Definition: multi.h:459
#define MV_CODE_DENY_TOKEN
Definition: multi_voice.cpp:47
void rtvoice_stop_recording()
Definition: rtvoice.cpp:187
void multi_voice_take_token(int stream_index)
#define ADD_DATA(d)
Definition: multimsgs.h:37
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
void multi_io_send(net_player *pl, ubyte *data, int len)
Definition: multimsgs.cpp:371
Assert(pm!=NULL)
int target_objnum
Definition: ai.h:339
int Multi_voice_local_prefs
void multi_voice_set_vars(int qos, int duration)
ushort net_signature
Definition: object.h:163
#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
Definition: multi_voice.cpp:62
void rtvoice_get_data(unsigned char **outbuf, int *size, double *gain)
Definition: rtvoice.cpp:279
#define VOICE_PACKET
Definition: multi.h:247
#define KEY_LSHIFT
Definition: key.h:134
void multi_io_send_reliable(net_player *pl, ubyte *data, int len)
Definition: multimsgs.cpp:459
int find_player_id(short player_id)
Definition: multiutil.cpp:465
#define MULTI_VOICE_TOKEN_TIMEOUT
#define MULTI_VOICE_MAX_STREAMS
Definition: multi_voice.cpp:95
#define f2fl(fx)
Definition: floating.h:37
#define MV_CODE_TAKE_TOKEN
Definition: multi_voice.cpp:48
fix t2
Definition: animplay.cpp:37
voice_stream Multi_voice_stream[MULTI_VOICE_MAX_STREAMS]
GLenum mode
Definition: Glext.h:5794
int multi_voice_status()
int stream_rtvoice_handle
ubyte Multi_voice_next_stream_id
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
int flags
Definition: multi.h:463
#define MULTI_VOICE_KEY
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
void rtvoice_set_qos(int qos)
Definition: rtvoice.cpp:140
#define MV_CODE_DATA
Definition: multi_voice.cpp:52
int packet_size
Definition: multi_sexp.cpp:41
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
int Multi_voice_send_mode
Definition: multi_voice.cpp:43
void multi_voice_free_all()
int Multi_voice_token
#define MULTI_MSG_NONE
Definition: multi_pmsg.h:26
int Multi_voice_test_packet_tossed
void multi_voice_process_next_chunk()
int Multi_voice_recording
void multi_voice_process()
#define GET_FLOAT(d)
Definition: multimsgs.h:52
#define MULTI_VOICE_TOKEN_RELEASE_WAIT
HWND DWORD code
Definition: vddraw.h:425
void multi_voice_reset()
void multi_voice_close()
int Multi_voice_qos
Definition: multi_voice.cpp:57
#define MAX_PACKET_SIZE
Definition: psnet2.h:34
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)
Definition: multiutil.cpp:2895
char * Multi_voice_record_buffer
Definition: multi_voice.cpp:86
GLintptr offset
Definition: Glext.h:5497
net_player_info p_info
Definition: multi.h:473
void multi_voice_test_process_next_chunk()
void options_multi_set_voice_data(unsigned char *sound_buf, int buf_size, double gain)
#define MULTI_VOICE_MAX_TIME
Definition: multi_voice.h:28
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
void rtvoice_close_recording()
Definition: rtvoice.cpp:209
#define ADD_FLOAT(d)
Definition: multimsgs.h:42
#define nprintf(args)
Definition: pstypes.h:239
multi_server_options options
Definition: multi.h:514
int Multi_voice_can_record
Definition: multi_voice.cpp:41
#define BUILD_HEADER(t)
Definition: multimsgs.h:36
int snd_get_data(int handle, char *data)
Definition: sound.cpp:1232
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
Definition: multi_voice.cpp:53
netgame_info Netgame
Definition: multi.cpp:97
#define MULTI_VOICE_POST_SOUND
Definition: multi_voice.cpp:61
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
Definition: multi_voice.cpp:50
void multi_voice_maybe_update_vars(int new_qos, int new_duration)
int rtvoice_play(int index, unsigned char *data, int size)
Definition: rtvoice.cpp:437
net_player_server_info s_info
Definition: multi.h:472
#define MV_CODE_GIVE_TOKEN
Definition: multi_voice.cpp:46
#define MV_DEFAULT_QOS
Definition: multi_voice.cpp:56
void multi_voice_dcf()
#define MAX_PLAYERS
Definition: pstypes.h:32
short player_id
Definition: multi.h:460
char * Multi_voice_playback_buffer
Definition: multi_voice.cpp:87
#define ADD_SHORT(d)
Definition: multimsgs.h:38
void multi_voice_player_process()
int snd_size(int handle, int *size)
Definition: sound.cpp:1244
#define MV_ALG_TIMEOUT
Definition: multi_voice.cpp:99
int idx
Definition: multiui.cpp:761
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]
Definition: object.cpp:62
long fix
Definition: pstypes.h:54
unsigned char ubyte
Definition: pstypes.h:62
#define MLO_FLAG_NO_VOICE
#define MULTI_MSG_ALL
Definition: multi_pmsg.h:27
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define GM_IN_MISSION
Definition: systemvars.h:23
#define MULTI_MSG_HOSTILE
Definition: multi_pmsg.h:29
void rtvoice_stop_playback(int index)
Definition: rtvoice.cpp:399
int Multi_voice_denied_stamp
int Multi_voice_max_time
Definition: multi_voice.cpp:85
#define NOX(s)
Definition: pstypes.h:473
int Multi_voice_current_stream_sent
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
void rtvoice_uncompress(unsigned char *data_in, int size_in, double gain, unsigned char *data_out, int size_out)
Definition: rtvoice.cpp:300
#define MV_TEST_RECORD_TIME
#define vm_malloc(size)
Definition: pstypes.h:547
int Multi_voice_player_prefs[MAX_PLAYERS]
int multi_voice_keydown()
#define ADD_USHORT(d)
Definition: multimsgs.h:39
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
Definition: multi.h:598
int multi_msg_voice_record()
Definition: multi_pmsg.cpp:119
void multi_voice_request_token()
GLuint GLfloat * val
Definition: Glext.h:6741
fix t1
Definition: animplay.cpp:37
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
Definition: multi_voice.cpp:60
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
Definition: multi_voice.cpp:75
#define MULTI_CONNECTED(np)
Definition: multi.h:136
int multi_voice_mix(int post_sound, char *data, int cur_size, int max_size)
fix timer_get_fixed_seconds()
Definition: timer.cpp:116
#define GET_USHORT(d)
Definition: multimsgs.h:49
GLenum target
Definition: Glext.h:6872
Definition: multi.h:385
ubyte accum_buffer_flags[MULTI_VOICE_ACCUM_BUFFER_COUNT]
int Multi_voice_inited
Definition: multi_voice.cpp:40
unsigned short ushort
Definition: pstypes.h:63
int Multi_voice_can_play
Definition: multi_voice.cpp:42
int HEADER_LENGTH
Definition: multi.cpp:106
void rtvoice_close_playback()
Definition: rtvoice.cpp:308
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]
Definition: key.cpp:42
#define MULTI_VOICE_STATUS_DENIED
Definition: multi_voice.h:23
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int multi_voice_stream_playing(int stream_index)
#define timestamp_elapsed(stamp)
Definition: timer.h:102
short id
Definition: multi.h:390
int Multi_voice_recording_stamp
int multi_voice_process_player_prefs(ubyte *data, int player_index)
#define MULTI_MSG_TARGET
Definition: multi_pmsg.h:30
#define MULTI_VOICE_ACCUM_BUFFER_SIZE
Definition: multi_voice.cpp:78
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)
#define GET_SHORT(d)
Definition: multimsgs.h:48
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.
Definition: console.cpp:358
int rtvoice_create_playback_buffer()
Definition: rtvoice.cpp:378
void multi_voice_client_send_pending()
#define MULTI_VOICE_TOKEN_INDEX_RELEASED
void rtvoice_stop_playback_all()
Definition: rtvoice.cpp:410
void multi_voice_init()
void multi_voice_server_process()
int rtvoice_start_recording(void(*user_callback)(), int callback_time)
Definition: rtvoice.cpp:233
void multi_voice_release_token()
#define MULTI_VOICE_STATUS_PLAYING
Definition: multi_voice.h:25
int Multi_voice_keydown
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
void multi_voice_alg_process_data(int stream_index)
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
int multi_voice_find_token(int player_index)
#define MULTI_VOICE_ACCUM_BUFFER_COUNT
Definition: multi_voice.cpp:83
multi_global_options Multi_options_g
void multi_voice_test_process()
int multi_find_player_by_net_signature(ushort net_signature)
Definition: multiutil.cpp:537
ubyte * accum_buffer[MULTI_VOICE_ACCUM_BUFFER_COUNT]
int multi_msg_mode()
Definition: multi_pmsg.cpp:157
multi_local_options options
Definition: multi.h:452
int multi_voice_test_get_playback_buffer()
#define MV_CODE_PLAYER_PREFS
Definition: multi_voice.cpp:51
#define KEY_RSHIFT
Definition: key.h:135