00001
00002 #include "revolt.h"
00003 #include "sfx.h"
00004 #include "main.h"
00005 #include "geom.h"
00006 #include "camera.h"
00007 #include "timing.h"
00008
00009
00010
00011 long SoundOff;
00012
00013 static SFX_LOAD SfxLoad[SFX_MAX_LOAD];
00014 static SAMPLE_SFX Sample[SFX_MAX_SAMPLES];
00015 static SAMPLE_3D Sample3D[SFX_MAX_SAMPLES_3D];
00016 static long SfxSampleNum, SfxLoadNum;
00017 static DIG_DRIVER *DigDriver;
00018 static unsigned long SfxTimerLast, SfxTimerCurrent;
00019 static float SfxTimeMul;
00020 static HSTREAM StreamMP3;
00021
00022
00023
00024 static char *SfxGeneric[] = {
00025 "wavs\\moto.wav",
00026 "wavs\\honkgood.wav",
00027 "wavs\\scrape1.wav",
00028 "wavs\\screech.wav",
00029 "wavs\\woohoo.wav",
00030 "wavs\\pickup.wav",
00031 "wavs\\pickup2.wav",
00032 "wavs\\shock.wav",
00033 "wavs\\electro.wav",
00034 "wavs\\firework.wav",
00035 "wavs\\firebang.wav",
00036 "wavs\\ball.wav",
00037 "wavs\\ballhit.wav",
00038 "wavs\\wbomb.wav",
00039 "wavs\\wbombhit.wav",
00040 "wavs\\puttbang.wav",
00041 "wavs\\fuse.wav",
00042
00043 NULL
00044 };
00045
00046
00047
00048 static char *SfxToy[] = {
00049 "wavs\\piano.wav",
00050 "wavs\\plane.wav",
00051 "wavs\\copter.wav",
00052 "wavs\\dragon.wav",
00053 "wavs\\creak.wav",
00054 "wavs\\train.wav",
00055 "wavs\\whistle.wav",
00056
00057 NULL
00058 };
00059
00060
00061
00062 LEVEL_SFX SfxLevel[] = {
00063 "TOYLITE", SfxToy,
00064 "TOY2", SfxToy,
00065
00066 NULL
00067 };
00068
00070
00072
00073 long InitSound(void)
00074 {
00075 long r;
00076 WAVEFORMATEX format;
00077
00078
00079
00080 if (SoundOff)
00081 return TRUE;
00082
00083
00084
00085 r = AIL_startup();
00086 if (!r)
00087 {
00088 Box(NULL, "Failed to init sound system!", MB_OK);
00089 SoundOff = TRUE;
00090 return FALSE;
00091 }
00092
00093
00094
00095 AIL_set_preference(DIG_USE_WAVEOUT, NO);
00096
00097
00098
00099 format.wFormatTag = WAVE_FORMAT_PCM;
00100 format.nChannels = SFX_NUM_CHANNELS;
00101 format.nSamplesPerSec = SFX_SAMPLE_RATE;
00102 format.nAvgBytesPerSec = SFX_SAMPLE_RATE * (SFX_BITS_PER_SAMPLE / 8) * SFX_NUM_CHANNELS;
00103 format.nBlockAlign = (SFX_BITS_PER_SAMPLE / 8) * SFX_NUM_CHANNELS;
00104 format.wBitsPerSample = SFX_BITS_PER_SAMPLE;
00105
00106 r = AIL_waveOutOpen(&DigDriver, NULL, NULL, (WAVEFORMAT*)&format);
00107 if (r)
00108 {
00109 Box(NULL, "Failed to set sound format!", MB_OK);
00110 SoundOff = TRUE;
00111 return FALSE;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 return TRUE;
00124 }
00125
00127
00129
00130 void ReleaseSound(void)
00131 {
00132
00133
00134
00135 if (SoundOff)
00136 return;
00137
00138
00139
00140 AIL_shutdown();
00141 }
00142
00144
00146
00147 long LoadSfx(char *levelname)
00148 {
00149 long i;
00150 char buf[128];
00151 char **wavs;
00152
00153
00154
00155 if (SoundOff)
00156 return TRUE;
00157
00158
00159
00160 wavs = SfxGeneric;
00161
00162 for (i = 0 ; i < SFX_MAX_LOAD ; i++)
00163 {
00164
00165
00166
00167 if (!wavs[i]) break;
00168
00169
00170
00171 SfxLoad[i].Pos = AIL_file_read(wavs[i], NULL);
00172 if (!SfxLoad[i].Pos)
00173 {
00174 wsprintf(buf, "Can't load '%s' into slot %d!", wavs[i], i);
00175 Box(NULL, buf, MB_OK);
00176 }
00177 else
00178 {
00179 SfxLoad[i].Size = AIL_file_size(wavs[i]);
00180 }
00181 }
00182
00183 SfxLoadNum = i;
00184
00185
00186
00187 i = 0;
00188 while (SfxLevel[i].Name && strcmp(SfxLevel[i].Name, levelname)) i++;
00189
00190 if (SfxLevel[i].Name)
00191 {
00192 wavs = SfxLevel[i].Files;
00193
00194 for (i = SfxLoadNum ; i < SFX_MAX_LOAD ; i++)
00195 {
00196
00197
00198
00199 if (!wavs[i - SfxLoadNum]) break;
00200
00201
00202
00203 SfxLoad[i].Pos = AIL_file_read(wavs[i - SfxLoadNum], NULL);
00204 if (!SfxLoad[i].Pos)
00205 {
00206 wsprintf(buf, "Can't load '%s' into slot %d!", wavs[i - SfxLoadNum], i);
00207 Box(NULL, buf, MB_OK);
00208 }
00209 else
00210 {
00211 SfxLoad[i].Size = AIL_file_size(wavs[i - SfxLoadNum]);
00212 }
00213 }
00214
00215 SfxLoadNum = i;
00216 }
00217
00218
00219
00220 for (i = 0 ; i < SFX_MAX_SAMPLES ; i++)
00221 {
00222 Sample[i].Handle = AIL_allocate_sample_handle(DigDriver);
00223 if (!Sample[i].Handle) break;
00224 AIL_init_sample(Sample[i].Handle);
00225 }
00226
00227 SfxSampleNum = i;
00228
00229
00230
00231 for (i = 0 ; i < SFX_MAX_SAMPLES_3D ; i++)
00232 {
00233 Sample3D[i].Alive = FALSE;
00234 }
00235
00236
00237
00238 return TRUE;
00239 }
00240
00242
00244
00245 void FreeSfx(void)
00246 {
00247 long i;
00248
00249
00250
00251 if (SoundOff)
00252 return;
00253
00254
00255
00256 for (i = 0 ; i < SfxLoadNum ; i++)
00257 {
00258 if (SfxLoad[i].Pos)
00259 AIL_mem_free_lock(SfxLoad[i].Pos);
00260 }
00261
00262
00263
00264 for (i = 0 ; i <SfxSampleNum ; i++)
00265 {
00266 AIL_release_sample_handle(Sample[i].Handle);
00267 }
00268 }
00269
00271
00273
00274 void PlaySfx(long num, long vol, long pan, long freq)
00275 {
00276 long i;
00277
00278
00279
00280 if (SoundOff)
00281 return;
00282
00283
00284
00285 if (!SfxLoad[num].Pos)
00286 return;
00287
00288
00289
00290 for (i = 0 ; i < SfxSampleNum ; i++)
00291 {
00292 if (AIL_sample_status(Sample[i].Handle) == SMP_DONE)
00293 {
00294
00295
00296
00297 AIL_init_sample(Sample[i].Handle);
00298 AIL_set_sample_file(Sample[i].Handle, SfxLoad[num].Pos, -1);
00299
00300 if (vol != -1) AIL_set_sample_volume(Sample[i].Handle, vol);
00301 if (pan != -1) AIL_set_sample_pan(Sample[i].Handle, pan);
00302 if (freq != -1) AIL_set_sample_playback_rate(Sample[i].Handle, freq);
00303
00304 AIL_start_sample(Sample[i].Handle);
00305 break;
00306 }
00307 }
00308 }
00309
00311
00313
00314 void StopSfx(SAMPLE_SFX *sample)
00315 {
00316
00317
00318 if (SoundOff)
00319 return;
00320
00321
00322
00323 AIL_end_sample(sample->Handle);
00324 }
00325
00327
00329
00330 void PauseAllSfx()
00331 {
00332 long i;
00333
00334 for (i = 0 ; i < SfxSampleNum ; i++)
00335 {
00336 if (AIL_sample_status(Sample[i].Handle) == SMP_PLAYING)
00337 {
00338 AIL_stop_sample(Sample[i].Handle);
00339 }
00340 }
00341 }
00342
00344
00346
00347 void ResumeAllSfx()
00348 {
00349 long i;
00350
00351 for (i = 0 ; i < SfxSampleNum ; i++)
00352 {
00353 if (AIL_sample_status(Sample[i].Handle) == SMP_STOPPED)
00354 {
00355 AIL_resume_sample(Sample[i].Handle);
00356 }
00357 }
00358 }
00359
00361
00363
00364 void PlaySfx3D(long num, long vol, long freq, VEC *pos)
00365 {
00366 long pan;
00367
00368
00369
00370 if (SoundOff)
00371 return;
00372
00373
00374
00375 GetSfxSettings3D(&vol, &freq, &pan, pos, 0);
00376
00377
00378
00379 PlaySfx(num, vol, pan, freq);
00380 }
00381
00383
00385
00386 SAMPLE_3D *CreateSfx3D(long num, long vol, long freq, long loop, VEC *pos)
00387 {
00388 long i, j;
00389
00390
00391
00392 if (SoundOff)
00393 return NULL;
00394
00395
00396
00397 for (i = 0 ; i < SFX_MAX_SAMPLES_3D ; i++) if (!Sample3D[i].Alive)
00398 {
00399
00400
00401
00402 Sample3D[i].Num = num;
00403 Sample3D[i].Vol = vol;
00404 Sample3D[i].Freq = freq;
00405 Sample3D[i].Loop = loop;
00406 Sample3D[i].LastDist = 0;
00407 Sample3D[i].Pos = *pos;
00408
00409
00410
00411 if (loop)
00412 {
00413 Sample3D[i].Sample = NULL;
00414 Sample3D[i].Alive = TRUE;
00415 return &Sample3D[i];
00416 }
00417
00418
00419
00420 if (!SfxLoad[num].Pos)
00421 return NULL;
00422
00423
00424
00425 for (j = 0 ; j < SfxSampleNum ; j++)
00426 {
00427 if (AIL_sample_status(Sample[j].Handle) == SMP_DONE)
00428 {
00429 AIL_init_sample(Sample[j].Handle);
00430 AIL_set_sample_file(Sample[j].Handle, SfxLoad[Sample3D[i].Num].Pos, -1);
00431 AIL_set_sample_loop_count(Sample[j].Handle, 1);
00432 AIL_set_sample_volume(Sample[j].Handle, SFX_MIN_VOL);
00433 AIL_start_sample(Sample[j].Handle);
00434
00435 Sample3D[i].Sample = &Sample[j];
00436 Sample3D[i].Alive = TRUE;
00437 return &Sample3D[i];
00438 }
00439 }
00440
00441
00442
00443 return NULL;
00444 }
00445
00446
00447
00448 return NULL;
00449 }
00450
00452
00454
00455 void FreeSfx3D(SAMPLE_3D *sample3d)
00456 {
00457
00458
00459
00460 if (SoundOff)
00461 return;
00462
00463
00464
00465 if (sample3d->Sample)
00466 {
00467 StopSfx(sample3d->Sample);
00468 }
00469
00470
00471
00472 sample3d->Alive = FALSE;
00473 }
00474
00476
00478
00479 void GetSfxSettings3D(long *vol, long *freq, long *pan, VEC *pos, float vel)
00480 {
00481 long per;
00482 float x, f;
00483 VEC vec1, vec2;
00484
00485
00486
00487 if (SoundOff)
00488 return;
00489
00490
00491
00492 SubVector(pos, &CAM_MainCamera->WPos, &vec1);
00493 TransposeRotVector(&CAM_MainCamera->WMatrix, &vec1, &vec2);
00494
00495
00496
00497 f = SFX_3D_MIN_DIST / Length(&vec2) - SFX_3D_SUB_DIST;
00498 if (f < 0) f = 0;
00499 else if (f > 1) f = 1;
00500
00501 FTOL(f * 256, per);
00502 *vol = *vol * per / 256;
00503
00504
00505
00506 x = vec2.v[X] * RenderSettings.GeomPers / abs(vec2.v[Z]);
00507 x = (x * SFX_3D_PAN_MUL / REAL_SCREEN_XSIZE) + SFX_CENTRE_PAN;
00508 if (x < SFX_LEFT_PAN + 1) x = SFX_LEFT_PAN + 1;
00509 else if (x > SFX_RIGHT_PAN - 1) x = SFX_RIGHT_PAN - 1;
00510
00511 FTOL(x, *pan);
00512
00513
00514
00515 f = SFX_3D_SOS / (vel + SFX_3D_SOS);
00516
00517 FTOL(f * 256, per);
00518 *freq = *freq * per / 256;
00519 }
00520
00522
00524
00525 void ChangeSfxSample3D(SAMPLE_3D *sample3d, long sfx)
00526 {
00527 if (sample3d->Sample)
00528 {
00529 StopSfx(sample3d->Sample);
00530 sample3d->Sample = NULL;
00531 }
00532
00533 sample3d->Num = sfx;
00534 }
00535
00537
00539
00540 void MaintainAllSfx(void)
00541 {
00542 long i, j, vol, freq, pan;
00543 float dist, vel;
00544 VEC vec;
00545
00546
00547
00548 if (SoundOff)
00549 return;
00550
00551
00552
00553 SfxTimerLast = SfxTimerCurrent;
00554 SfxTimerCurrent = CurrentTimer();
00555 SfxTimeMul = ((float)TimerFreq / 100) / (float)(SfxTimerCurrent - SfxTimerLast);
00556
00557
00558
00559 for (i = 0 ; i < SFX_MAX_SAMPLES_3D ; i++) if (Sample3D[i].Alive)
00560 {
00561
00562
00563
00564 if (!Sample3D[i].Loop)
00565 {
00566 if (Sample3D[i].Sample)
00567 {
00568 if (AIL_sample_status(Sample3D[i].Sample->Handle) == SMP_DONE)
00569 Sample3D[i].Sample = NULL;
00570 }
00571 if (!Sample3D[i].Sample)
00572 continue;
00573 }
00574
00575
00576
00577 SubVector(&Sample3D[i].Pos, &CAM_MainCamera->WPos, &vec);
00578 dist = Length(&vec);
00579 vel = (dist - Sample3D[i].LastDist) * SfxTimeMul;
00580 Sample3D[i].LastDist = dist;
00581
00582 vol = Sample3D[i].Vol;
00583 freq = Sample3D[i].Freq;
00584
00585 GetSfxSettings3D(&vol, &freq, &pan, &Sample3D[i].Pos, vel);
00586
00587
00588
00589 if (Sample3D[i].Loop && !vol)
00590 {
00591 if (Sample3D[i].Sample)
00592 {
00593 StopSfx(Sample3D[i].Sample);
00594 Sample3D[i].Sample = NULL;
00595 }
00596
00597 continue;
00598 }
00599
00600
00601
00602 if (Sample3D[i].Loop && !Sample3D[i].Sample && SfxLoad[Sample3D[i].Num].Pos)
00603 {
00604 for (j = 0 ; j < SfxSampleNum ; j++)
00605 {
00606 if (AIL_sample_status(Sample[j].Handle) == SMP_DONE)
00607 {
00608 AIL_init_sample(Sample[j].Handle);
00609 AIL_set_sample_file(Sample[j].Handle, SfxLoad[Sample3D[i].Num].Pos, -1);
00610 AIL_set_sample_loop_count(Sample[j].Handle, 0);
00611 AIL_set_sample_volume(Sample[j].Handle, SFX_MIN_VOL);
00612 AIL_start_sample(Sample[j].Handle);
00613
00614 Sample3D[i].Sample = &Sample[j];
00615 break;
00616 }
00617 }
00618 }
00619
00620
00621
00622 if (!Sample3D[i].Sample)
00623 continue;
00624
00625
00626
00627 AIL_set_sample_volume(Sample3D[i].Sample->Handle, vol);
00628 AIL_set_sample_pan(Sample3D[i].Sample->Handle, pan);
00629 AIL_set_sample_playback_rate(Sample3D[i].Sample->Handle, freq);
00630 }
00631 }
00632
00634
00636
00637 void PlayMP3(char *file)
00638 {
00639 StreamMP3 = AIL_open_stream(DigDriver, file, 0);
00640 AIL_set_stream_loop_count(StreamMP3, 0);
00641 AIL_set_stream_volume(StreamMP3, SFX_MAX_VOL);
00642 AIL_set_stream_playback_rate(StreamMP3, 44100);
00643 AIL_start_stream(StreamMP3);
00644 }
00645
00647
00649
00650 void StopMP3()
00651 {
00652 AIL_close_stream(StreamMP3);
00653 }