1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7
8 **************************************************************************
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ***************************************************************************
25
26 */
27
28 #include "eSound.h"
29 #include "config.h"
30 #include "tMemManager.h"
31 #include "tDirectories.h"
32 #include "tRandom.h"
33 #include "tError.h"
34 #include <string>
35 #include "tConfiguration.h"
36 #include "uMenu.h"
37 #include "eCamera.h"
38 //#include "tList.h"
39 #include <iostream>
40 #include <stdlib.h>
41 #include "eGrid.h"
42 #include "tException.h"
43
44 //eGrid* eSoundPlayer::S_Grid = NULL;
45
46 #ifdef WIN32
47 #define HAVE_LIBSDL_MIXER 1
48 #endif
49
50 #ifndef DEDICATED
51 #ifdef HAVE_LIBSDL_MIXER
52 #include <SDL_mixer.h>
53 static Mix_Music* music = NULL;
54 #endif
55
56 static SDL_AudioSpec audio;
57 static bool sound_is_there=false;
58 static bool uses_sdl_mixer=false;
59 #endif
60
61 // sound quality
62
63 #define SOUND_OFF 0
64 #define SOUND_LOW 1
65 #define SOUND_MED 2
66 #define SOUND_HIGH 3
67
68 #ifdef WIN32
69 static int buffer_shift=1;
70 #else
71 static int buffer_shift=0;
72 #endif
73
74 static tConfItem<int> bs("SOUND_BUFFER_SHIFT",buffer_shift);
75
76 static int sound_quality=SOUND_MED;
77 static tConfItem<int> sq("SOUND_QUALITY",sound_quality);
78
79 static int sound_sources=10;
80 static tConfItem<int> ss("SOUND_SOURCES",sound_sources);
81 static REAL loudness_thresh=0;
82 static int real_sound_sources=0;
83
84 static tList<eSoundPlayer> se_globalPlayers;
85
86
fill_audio(void * udata,Uint8 * stream,int len)87 void fill_audio(void *udata, Uint8 *stream, int len)
88 {
89 #ifndef DEDICATED
90 real_sound_sources=0;
91 int i;
92 if (eGrid::CurrentGrid())
93 for(i=eGrid::CurrentGrid()->Cameras().Len()-1;i>=0;i--)
94 {
95 eCamera *pCam = eGrid::CurrentGrid()->Cameras()(i);
96 if(pCam)
97 pCam->SoundMix(stream,len);
98 }
99
100 for(i=se_globalPlayers.Len()-1;i>=0;i--)
101 se_globalPlayers(i)->Mix(stream,len,0,1,1);
102
103 if (real_sound_sources>sound_sources+4)
104 loudness_thresh+=.01;
105 if (real_sound_sources>sound_sources+1)
106 loudness_thresh+=.001;
107 if (real_sound_sources<sound_sources-4)
108 loudness_thresh-=.001;
109 if (real_sound_sources<sound_sources-1)
110 loudness_thresh-=.0001;
111 if (loudness_thresh<0)
112 loudness_thresh=0;
113 #endif
114 }
115
116 #ifndef DEDICATED
117 #ifdef DEFAULT_SDL_AUDIODRIVER
118
119 // stringification, yep, two levels required
120 #define XSTRING(s) #s
121 #define STRING(s) XSTRING(s)
122
123 // call once to initialize SDL sound subsystem
se_SoundInitPrepare()124 static bool se_SoundInitPrepare()
125 {
126 // initialize audio subsystem with predefined, hopefully good, driver
127 if ( ! getenv("SDL_AUDIODRIVER") ) {
128 char * arg = "SDL_AUDIODRIVER=" STRING(DEFAULT_SDL_AUDIODRIVER);
129 putenv(arg);
130
131 if ( SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0 )
132 return true;
133
134 putenv("SDL_AUDIODRIVER=");
135 }
136
137 // if that fails, try what the user wanted
138 return ( SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0 );
139 }
140 #endif
141 #endif
142
se_SoundInit()143 void se_SoundInit()
144 {
145 #ifndef DEDICATED
146 // save configuration file with sound disabled on first use so we don't try again
147 bool needSave = false;
148 static bool firstRun = true;
149 if ( st_FirstUse )
150 {
151 needSave = true;
152 int sound_quality_back = sound_quality;
153 sound_quality = SOUND_OFF;
154 st_SaveConfig();
155 if ( firstRun )
156 con << tOutput("$sound_firstinit");
157 sound_quality=sound_quality_back;
158 }
159
160 if ( sound_quality != SOUND_OFF )
161 {
162 #ifdef DEFAULT_SDL_AUDIODRIVER
163 static bool init = se_SoundInitPrepare();
164 if ( !init )
165 return;
166 #endif
167 if ( firstRun && !SDL_WasInit( SDL_INIT_AUDIO ) )
168 return;
169 firstRun = false;
170 }
171
172 if (!sound_is_there && sound_quality!=SOUND_OFF)
173 {
174 SDL_AudioSpec desired;
175
176 switch (sound_quality)
177 {
178 case SOUND_LOW:
179 desired.freq=11025; break;
180 case SOUND_MED:
181 desired.freq=22050; break;
182 case SOUND_HIGH:
183 desired.freq=44100; break;
184 default:
185 desired.freq=22050;
186 }
187
188 desired.format=AUDIO_S16SYS;
189 desired.samples=128;
190 while (desired.samples <= desired.freq >> (6-buffer_shift))
191 desired.samples <<= 1;
192 desired.channels = 2;
193 desired.callback = fill_audio;
194 desired.userdata = NULL;
195
196 #ifdef HAVE_LIBSDL_MIXER
197 uses_sdl_mixer=true;
198
199 // init using SDL_Mixer
200 sound_is_there=(Mix_OpenAudio(desired.freq, desired.format, desired.channels, desired.samples)>=0);
201
202 if ( sound_is_there )
203 {
204 // query actual sound info
205 audio = desired;
206 int channels;
207 Mix_QuerySpec( &audio.freq, &audio.format, &channels );
208 audio.channels = channels;
209
210 // register callback
211 Mix_SetPostMix( &fill_audio, NULL );
212
213 const tPath& vpath = tDirectories::Data();
214 tString musFile = vpath.GetReadPath( "music/fire.xm" );
215
216 music = Mix_LoadMUS( musFile );
217
218 if ( music )
219 Mix_FadeInMusic( music, -1, 2000 );
220
221 }
222 #else
223 // just use SDL to init sound
224 uses_sdl_mixer=false;
225 sound_is_there=(SDL_OpenAudio(&desired,&audio)>=0);
226 #endif
227 if (sound_is_there && (audio.format!=AUDIO_S16SYS || audio.channels!=2))
228 {
229 uses_sdl_mixer=false;
230 se_SoundExit();
231 // force emulation of 16 bit stereo; sadly, this cannot use SDL_Mixer :-(
232 audio.format=AUDIO_S16SYS;
233 audio.channels=2;
234 sound_is_there=(SDL_OpenAudio(&audio,NULL)>=0);
235 con << tOutput("$sound_error_no16bit");
236 }
237 if (!sound_is_there)
238 con << tOutput("$sound_error_initfailed");
239 else
240 {
241 //for(int i=wavs.Len()-1;i>=0;i--)
242 //wavs(i)->Init();
243 #ifdef DEBUG
244 tOutput o;
245 o.SetTemplateParameter(1,audio.freq);
246 o.SetTemplateParameter(2,audio.samples);
247 o << "$sound_inited";
248 con << o;
249 #endif
250 se_SoundPause(false);
251 }
252 }
253
254 // save sound settings, they appear to work
255 if ( needSave )
256 {
257 st_SaveConfig();
258 }
259 #endif
260 }
261
se_SoundExit()262 void se_SoundExit(){
263 #ifndef DEDICATED
264 eSoundLocker locker;
265
266 eWavData::UnloadAll();
267 se_SoundPause(true);
268
269 if (sound_is_there){
270 #ifdef DEBUG
271 con << tOutput("$sound_disabling");
272 #endif
273 // se_SoundPause(false);
274 // for(int i=wavs.Len()-1;i>=0;i--)
275 //wavs(i)->Exit();
276
277 #ifdef HAVE_LIBSDL_MIXER
278 if ( music )
279 {
280 if( Mix_PlayingMusic() )
281 {
282 Mix_FadeOutMusic(100);
283 SDL_Delay(100);
284 }
285 Mix_FreeMusic( music );
286 music = NULL;
287 }
288
289 se_SoundPause(true);
290
291 if ( uses_sdl_mixer )
292 Mix_CloseAudio();
293 else
294 #endif
295 SDL_CloseAudio();
296
297 #ifdef DEBUG
298 con << tOutput("$sound_disabling_done");
299 #endif
300 }
301 sound_is_there=false;
302 #endif
303 }
304
305 #ifndef DEDICATED
306 static unsigned int locks;
307 #endif
308
se_SoundLock()309 void se_SoundLock(){
310 #ifndef DEDICATED
311 if (!locks)
312 SDL_LockAudio();
313 locks++;
314 #endif
315 }
316
se_SoundUnlock()317 void se_SoundUnlock(){
318 #ifndef DEDICATED
319 locks--;
320 if (!locks)
321 SDL_UnlockAudio();
322 #endif
323 }
324
se_SoundPause(bool p)325 void se_SoundPause(bool p){
326 #ifndef DEDICATED
327 SDL_PauseAudio(p);
328 #endif
329 }
330
331 // ***********************************************************
332
333 eWavData* eWavData::s_anchor = NULL;
334
eWavData(const char * fileName,const char * alternative)335 eWavData::eWavData(const char * fileName,const char *alternative)
336 :tListItem<eWavData>(s_anchor),data(NULL),len(0),freeData(false), loadError(false){
337 //wavs.Add(this,id);
338 filename = fileName;
339 filename_alt = alternative;
340
341 }
342
Load()343 void eWavData::Load(){
344 //wavs.Add(this,id);
345
346 if (data)
347 {
348 loadError = false;
349 return;
350 }
351
352 #ifndef DEDICATED
353
354 static char const * errorName = "Sound Error";
355
356 freeData = false;
357
358 loadError = true;
359
360 alt=false;
361
362 const tPath& path = tDirectories::Data();
363
364 SDL_AudioSpec *result=SDL_LoadWAV( path.GetReadPath( filename ) ,&spec,&data,&len);
365 if (result!=&spec || !data){
366 if (filename_alt.Len()>1){
367 result=SDL_LoadWAV( path.GetReadPath( filename_alt ),&spec,&data,&len);
368 if (result!=&spec || !data)
369 {
370 tOutput err;
371 err.SetTemplateParameter(1, filename);
372 err << "$sound_error_filenotfound";
373 throw tGenericException(err, errorName);
374 }
375 else
376 alt=true;
377 }
378 else{
379 result=SDL_LoadWAV( path.GetReadPath( "sound/expl.wav" ) ,&spec,&data,&len);
380 if (result!=&spec || !data)
381 {
382 tOutput err;
383 err.SetTemplateParameter(1, "sound/expl.waw");
384 err << "$sound_error_filenotfount";
385 throw tGenericException(err, errorName);
386 }
387 else
388 len=0;
389 }
390 /*
391 tERR_ERROR("Sound file " << fileName << " not found. Have you called "
392 "Armagetron from the right directory?"); */
393 }
394
395 if (spec.format==AUDIO_S16SYS)
396 samples=len>>1;
397 // else if(spec.format==AUDIO_U8)
398 // samples=len;
399 else
400 {
401 // prepare error message
402 tOutput err;
403 err.SetTemplateParameter(1, filename);
404 err << "$sound_error_unsupported";
405
406 // convert to 16 bit system format
407 SDL_AudioCVT cvt;
408 if ( -1 == SDL_BuildAudioCVT( &cvt, spec.format, spec.channels, spec.freq, AUDIO_S16SYS, spec.channels, spec.freq ) )
409 {
410 throw tGenericException(err, errorName);
411 }
412
413 cvt.buf=reinterpret_cast<Uint8 *>( malloc( len * cvt.len_mult ) );
414 cvt.len=len;
415 memcpy(cvt.buf, data, len);
416 freeData = true;
417
418
419 if ( -1 == SDL_ConvertAudio( &cvt ) )
420 {
421 throw tGenericException(err, errorName);
422 }
423
424 SDL_FreeWAV( data );
425 data = cvt.buf;
426 spec.format = AUDIO_S16SYS;
427 len = len * cvt.len_mult;
428
429 samples = len >> 1;
430 }
431
432 samples/=spec.channels;
433
434 #ifdef DEBUG
435 #ifdef LINUX
436 con << "Sound file " << filename << " loaded: ";
437 switch (spec.format){
438 case AUDIO_S16SYS: con << "16 bit "; break;
439 case AUDIO_U8: con << "8 bit "; break;
440 default: con << "unknown "; break;
441 }
442 if (spec.channels==2)
443 con << "stereo ";
444 else
445 con << "mono ";
446
447 con << "at " << spec.freq << " Hz,\n";
448
449 con << samples << " samples in " << len << " bytes.\n";
450
451 loadError = false;
452 #endif
453 #endif
454 #endif
455 }
456
Unload()457 void eWavData::Unload(){
458 #ifndef DEDICATED
459 loadError = false;
460
461 //wavs.Add(this,id);
462 if (data){
463 eSoundLocker locker;
464 if ( freeData )
465 {
466
467 free(data);
468
469 }
470
471 else
472
473 {
474
475 SDL_FreeWAV(data);
476
477 }
478
479
480
481 data=NULL;
482 len=0;
483 }
484 #endif
485 }
486
UnloadAll()487 void eWavData::UnloadAll(){
488 //wavs.Add(this,id);
489 eWavData* wav = s_anchor;
490 while ( wav )
491 {
492 wav->Unload();
493 wav = wav->Next();
494 }
495
496 }
497
~eWavData()498 eWavData::~eWavData(){
499 #ifndef DEDICATED
500 Unload();
501 #endif
502 }
503
Mix(Uint8 * dest,Uint32 playlen,eAudioPos & pos,REAL Rvol,REAL Lvol,REAL Speed,bool loop)504 bool eWavData::Mix(Uint8 *dest,Uint32 playlen,eAudioPos &pos,
505 REAL Rvol,REAL Lvol,REAL Speed,bool loop){
506 #ifndef DEDICATED
507 if ( !data )
508 {
509 if( !loadError )
510 {
511 Load();
512 }
513 if ( !data )
514 {
515 return false;
516 }
517 }
518
519 playlen/=4;
520
521 // Rvol *= 4;
522 // Lvol *= 4;
523
524 const REAL thresh = .25;
525
526 if ( Rvol > thresh )
527 {
528 Rvol = thresh;
529 }
530
531 if ( Lvol > thresh )
532 {
533 Lvol = thresh;
534 }
535
536 #define SPEED_FRACTION (1<<20)
537
538 #define VOL_SHIFT 16
539 #define VOL_FRACTION (1<<VOL_SHIFT)
540
541 #define MAX_VAL ((1<<16)-1)
542 #define MIN_VAL -(1<<16)
543
544 // first, split the speed into the part before and after the decimal:
545 if (Speed<0) Speed=0;
546
547 // adjust for different sample rates:
548 Speed*=spec.freq;
549 Speed/=audio.freq;
550
551 int speed=int(floor(Speed));
552 int speed_fraction=int(SPEED_FRACTION*(Speed-speed));
553
554 // secondly, make integers out of the volumes:
555 int rvol=int(Rvol*VOL_FRACTION);
556 int lvol=int(Lvol*VOL_FRACTION);
557
558
559 bool goon=true;
560
561 while (goon){
562 if (spec.channels==2){
563 if (spec.format==AUDIO_U8)
564 while (playlen>0 && pos.pos<samples){
565 // fix endian problems for the Mac port, as well as support for other
566 // formats than stereo...
567 int l=((short *)dest)[0];
568 int r=((short *)dest)[1];
569 r += (rvol*(data[(pos.pos<<1) ]-128)) >> (VOL_SHIFT-8);
570 l += (lvol*(data[(pos.pos<<1)+1]-128)) >> (VOL_SHIFT-8);
571 if (r>MAX_VAL) r=MAX_VAL;
572 if (l>MAX_VAL) l=MAX_VAL;
573 if (r<MIN_VAL) r=MIN_VAL;
574 if (l<MIN_VAL) l=MIN_VAL;
575
576 ((short *)dest)[0]=l;
577 ((short *)dest)[1]=r;
578
579 dest+=4;
580
581 pos.pos+=speed;
582
583 pos.fraction+=speed_fraction;
584 while (pos.fraction>=SPEED_FRACTION){
585 pos.fraction-=SPEED_FRACTION;
586 pos.pos++;
587 }
588
589 playlen--;
590 }
591 else{
592 while (playlen>0 && pos.pos<samples){
593 int l=((short *)dest)[0];
594 int r=((short *)dest)[1];
595 r += (rvol*(((short *)data)[(pos.pos<<1) ])) >> VOL_SHIFT;
596 l += (lvol*(((short *)data)[(pos.pos<<1)+1])) >> VOL_SHIFT;
597 if (r>MAX_VAL) r=MAX_VAL;
598 if (l>MAX_VAL) l=MAX_VAL;
599 if (r<MIN_VAL) r=MIN_VAL;
600 if (l<MIN_VAL) l=MIN_VAL;
601
602 ((short *)dest)[0]=l;
603 ((short *)dest)[1]=r;
604
605 dest+=4;
606
607 pos.pos+=speed;
608
609 pos.fraction+=speed_fraction;
610 while (pos.fraction>=SPEED_FRACTION){
611 pos.fraction-=SPEED_FRACTION;
612 pos.pos++;
613 }
614 playlen--;
615 }
616 }
617 }
618 else{
619 if (spec.format==AUDIO_U8){
620 while (playlen>0 && pos.pos<samples){
621 // fix endian problems for the Mac port, as well as support for other
622 // formats than stereo...
623 int l=((short *)dest)[0];
624 int r=((short *)dest)[1];
625 int d=data[pos.pos]-128;
626 l += (lvol*d) >> (VOL_SHIFT-8);
627 r += (rvol*d) >> (VOL_SHIFT-8);
628 if (r>MAX_VAL) r=MAX_VAL;
629 if (l>MAX_VAL) l=MAX_VAL;
630 if (r<MIN_VAL) r=MIN_VAL;
631 if (l<MIN_VAL) l=MIN_VAL;
632
633 ((short *)dest)[0]=l;
634 ((short *)dest)[1]=r;
635
636 dest+=4;
637
638 pos.pos+=speed;
639
640 pos.fraction+=speed_fraction;
641 while (pos.fraction>=SPEED_FRACTION){
642 pos.fraction-=SPEED_FRACTION;
643 pos.pos++;
644 }
645
646 playlen--;
647 }
648 }
649 else
650 while (playlen>0 && pos.pos<samples){
651 int l=((short *)dest)[0];
652 int r=((short *)dest)[1];
653 int d=((short *)data)[pos.pos];
654 l += (lvol*d) >> VOL_SHIFT;
655 r += (rvol*d) >> VOL_SHIFT;
656 if (r>MAX_VAL) r=MAX_VAL;
657 if (l>MAX_VAL) l=MAX_VAL;
658 if (r<MIN_VAL) r=MIN_VAL;
659 if (l<MIN_VAL) l=MIN_VAL;
660
661 ((short *)dest)[0]=l;
662 ((short *)dest)[1]=r;
663
664 dest+=4;
665
666 pos.pos+=speed;
667
668 pos.fraction+=speed_fraction;
669 while (pos.fraction>=SPEED_FRACTION){
670 pos.fraction-=SPEED_FRACTION;
671 pos.pos++;
672 }
673 playlen--;
674 }
675 }
676
677 if (loop && pos.pos>=samples)
678 pos.pos-=samples;
679 else
680 goon=false;
681 }
682 #endif
683 return (playlen>0);
684
685 }
686
Loop()687 void eWavData::Loop(){
688 #ifndef DEDICATED
689 Uint8 *buff2=tNEW(Uint8) [len];
690
691 if (buff2){
692 memcpy(buff2,data,len);
693 Uint32 samples;
694
695 if (spec.format==AUDIO_U8){
696 samples=len;
697 for(int i=samples-1;i>=0;i--){
698 Uint32 j=i+((len>>2)<<1);
699 if (j>=len) j-=len;
700
701 REAL a=fabs(100*(j/REAL(samples)-.5));
702 if (a>1) a=1;
703 REAL b=1-a;
704
705 data[i]=int(a*buff2[i]+b*buff2[j]);
706 }
707 }
708 else if (spec.format==AUDIO_S16SYS){
709 samples=len>>1;
710 for(int i=samples-1;i>=0;i--){
711
712 /*
713 REAL a=2*i/REAL(samples);
714 if (a>1) a=2-a;
715 REAL b=1-a;
716 */
717
718
719 Uint32 j=i+((samples>>2)<<1);
720 while (j>=samples) j-=samples;
721
722 REAL a=fabs(100*(j/REAL(samples)-.5));
723 if (a>1) a=1;
724 REAL b=1-a;
725
726
727 ((short *)data)[i]=int(a*((short *)buff2)[i]+b*((short *)buff2)[j]);
728 }
729 }
730 delete[] buff2;
731 }
732
733 #endif
734 }
735
736
737 // ******************************************************************
738
Reset(int randomize)739 void eAudioPos::Reset(int randomize){
740 #ifndef DEDICATED
741 if (randomize){
742 tRandomizer & randomizer = tRandomizer::GetInstance();
743 fraction = randomizer.Get( SPEED_FRACTION );
744 // fraction=int(SPEED_FRACTION*(rand()/float(RAND_MAX)));
745 pos=randomizer.Get( randomize );
746 // pos=int(randomize*(rand()/float(RAND_MAX)));
747 }
748 else
749 fraction=pos=0;
750 #endif
751 }
752
753
754
eSoundPlayer(eWavData & w,bool l)755 eSoundPlayer::eSoundPlayer(eWavData &w,bool l)
756 :id(-1),wav(&w),loop(l){
757 if (l)
758 wav->Load();
759
760 for(int i=MAX_VIEWERS-1;i>=0;i--)
761 goon[i]=true;
762 }
763
~eSoundPlayer()764 eSoundPlayer::~eSoundPlayer()
765 {
766 eSoundLocker locker;
767 se_globalPlayers.Remove(this,id);
768 }
769
Mix(Uint8 * dest,Uint32 len,int viewer,REAL rvol,REAL lvol,REAL speed)770 bool eSoundPlayer::Mix(Uint8 *dest,
771 Uint32 len,
772 int viewer,
773 REAL rvol,
774 REAL lvol,
775 REAL speed){
776
777 if (goon[viewer]){
778 if (rvol+lvol>loudness_thresh){
779 real_sound_sources++;
780 return goon[viewer]=!wav->Mix(dest,len,pos[viewer],rvol,lvol,speed,loop);
781 }
782 else
783 return true;
784 }
785 else
786 return false;
787 }
788
Reset(int randomize)789 void eSoundPlayer::Reset(int randomize){
790 wav->Load();
791
792 for(int i=MAX_VIEWERS-1;i>=0;i--){
793 pos[i].Reset(randomize);
794 goon[i]=true;
795 }
796 }
797
End()798 void eSoundPlayer::End(){
799 for(int i=MAX_VIEWERS-1;i>=0;i--){
800 goon[i]=false;
801 }
802 }
803
804
MakeGlobal()805 void eSoundPlayer::MakeGlobal(){
806 wav->Load();
807
808 eSoundLocker locker;
809 se_globalPlayers.Add(this,id);
810 }
811
812
813 // ***************************************************************
814
815 uMenu Sound_menu("$sound_menu_text");
816
817 static uMenuItemInt sources_men
818 (&Sound_menu,"$sound_menu_sources_text",
819 "$sound_menu_sources_help",
820 sound_sources,2,20,2);
821
822 static uMenuItemSelection<int> sq_men
823 (&Sound_menu,"$sound_menu_quality_text",
824 "$sound_menu_quality_help",
825 sound_quality);
826
827
828 static uSelectEntry<int> a(sq_men,
829 "$sound_menu_quality_off_text",
830 "$sound_menu_quality_off_help",
831 SOUND_OFF);
832 static uSelectEntry<int> b(sq_men,
833 "$sound_menu_quality_low_text",
834 "$sound_menu_quality_low_help",
835 SOUND_LOW);
836 static uSelectEntry<int> c(sq_men,
837 "$sound_menu_quality_medium_text",
838 "$sound_menu_quality_medium_help",
839 SOUND_MED);
840 static uSelectEntry<int> d(sq_men,
841 "$sound_menu_quality_high_text",
842 "$sound_menu_quality_high_help",
843 SOUND_HIGH);
844
845 static uMenuItemSelection<int> bm_men
846 (&Sound_menu,
847 "$sound_menu_buffer_text",
848 "$sound_menu_buffer_help",
849 buffer_shift);
850
851 static uSelectEntry<int> ba(bm_men,
852 "$sound_menu_buffer_vsmall_text",
853 "$sound_menu_buffer_vsmall_help",
854 -2);
855
856 static uSelectEntry<int> bb(bm_men,
857 "$sound_menu_buffer_small_text",
858 "$sound_menu_buffer_small_help",
859 -1);
860
861 static uSelectEntry<int> bc(bm_men,
862 "$sound_menu_buffer_med_text",
863 "$sound_menu_buffer_med_help",
864 0);
865
866 static uSelectEntry<int> bd(bm_men,
867 "$sound_menu_buffer_high_text",
868 "$sound_menu_buffer_high_help",
869 1);
870
871 static uSelectEntry<int> be(bm_men,
872 "$sound_menu_buffer_vhigh_text",
873 "$sound_menu_buffer_vhigh_help",
874 2);
875
876
se_SoundMenu()877 void se_SoundMenu(){
878 // se_SoundPause(true);
879 // se_SoundLock();
880 int oldsettings=sound_quality;
881 int oldshift=buffer_shift;
882 Sound_menu.Enter();
883 if (oldsettings!=sound_quality || oldshift!=buffer_shift){
884 se_SoundExit();
885 se_SoundInit();
886 }
887 // se_SoundUnlock();
888 // se_SoundPause(false);
889 }
890
eSoundLocker()891 eSoundLocker::eSoundLocker()
892 {
893 se_SoundLock();
894 }
895
~eSoundLocker()896 eSoundLocker::~eSoundLocker()
897 {
898 se_SoundUnlock();
899 }
900
901