Subversion Repositories Games.Carmageddon

Rev

Rev 1 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "sound.h"
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #include "brender.h"
  7. #include "controls.h"
  8. #include "globvars.h"
  9. #include "graphics.h"
  10. #include "harness/trace.h"
  11. #include "opponent.h"
  12. #include "pd/sys.h"
  13. #include "piping.h"
  14. #include "replay.h"
  15. #include "s3/s3.h"
  16. #include "s3/s3_brender.h"
  17. #include "utility.h"
  18.  
  19. int gSound_detail_level;
  20. int gVirgin_pass = 1;
  21. int gOld_sound_detail_level = -1;
  22. int gLast_tune;
  23. int gRandom_MIDI_tunes[3];
  24. int gRandom_Rockin_MIDI_tunes[3];
  25. int gRandom_CDA_tunes[7];
  26. int gCDA_is_playing;
  27. int gServicing_sound;
  28. int gSong_repeat_count;
  29. int gSound_sources_inited;
  30. int gMusic_available;
  31. tS3_sound_tag gCDA_tag;
  32. int gCD_fully_installed;
  33. tS3_outlet_ptr gEffects_outlet;
  34. tS3_outlet_ptr gCar_outlet;
  35. tS3_outlet_ptr gEngine_outlet;
  36. tS3_outlet_ptr gDriver_outlet;
  37. tS3_outlet_ptr gPedestrians_outlet;
  38. tS3_outlet_ptr gMusic_outlet;
  39. tS3_sound_id gMIDI_id;
  40. tS3_outlet_ptr gIndexed_outlets[6];
  41. tU32 gLast_sound_service;
  42. int gCD_is_disabled;
  43. br_vector3 gCamera_left;
  44. br_vector3 gCamera_position;
  45. br_vector3 gOld_camera_position;
  46. br_vector3 gCamera_velocity;
  47.  
  48. // IDA: void __cdecl UsePathFileToDetermineIfFullInstallation()
  49. void UsePathFileToDetermineIfFullInstallation(void) {
  50.     // changed by dethrace for compatibility
  51.     // char line1[80];
  52.     // char line2[80];
  53.     // char line3[80];
  54.     // char path_file[80];
  55.     char line1[MAX_PATH_LENGTH];
  56.     char line2[MAX_PATH_LENGTH];
  57.     char line3[MAX_PATH_LENGTH];
  58.     char path_file[MAX_PATH_LENGTH];
  59.     FILE* fp;
  60.  
  61.     strcpy(path_file, gApplication_path);
  62.     strcat(path_file, gDir_separator);
  63.     strcat(path_file, "PATHS.TXT");
  64.     if (PDCheckDriveExists(path_file) != 0) {
  65.         fp = fopen(path_file, "rt");
  66.         if (fp) {
  67.             line1[0] = 0;
  68.             line2[0] = 0;
  69.             line3[0] = 0;
  70.             GetALineWithNoPossibleService(fp, (unsigned char*)line1);
  71.             GetALineWithNoPossibleService(fp, (unsigned char*)line2);
  72.             GetALineWithNoPossibleService(fp, (unsigned char*)line3);
  73.             fclose(fp);
  74.             if (strcmp(line3, "Full") == 0) {
  75.                 gCD_fully_installed = 1;
  76.             }
  77.         }
  78.     } else {
  79.         gCD_fully_installed = 1;
  80.     }
  81. }
  82.  
  83. // IDA: void __cdecl InitSound()
  84. void InitSound(void) {
  85.     tPath_name the_path;
  86.     //tS3_sound_tag tag; // Pierre-Marie Baty -- unused variable
  87.     int engine_channel_count;
  88.     int car_channel_count;
  89.     int ped_channel_count;
  90.  
  91.     if (gVirgin_pass) {
  92.         PathCat(the_path, gApplication_path, "SOUND");
  93.         if (gProgram_state.sausage_eater_mode) {
  94.             PathCat(the_path, the_path, "KSOUND.TXT");
  95.         } else {
  96.             PathCat(the_path, the_path, "SOUND.TXT");
  97.         }
  98.         if (gSound_override) {
  99.             gSound_enabled = 0;
  100.             gSound_available = 0;
  101.         } else {
  102.             gSound_enabled = S3Init(the_path, gAusterity_mode) == 0;
  103.             gSound_available = gSound_enabled;
  104.         }
  105.         S3Set3DSoundEnvironment(1.0f / WORLD_SCALE, -1.0, -1.0);
  106.         gVirgin_pass = 0;
  107.         gCD_is_disabled = 0;
  108.         UsePathFileToDetermineIfFullInstallation();
  109.     }
  110.     if (gSound_available == 0) {
  111.         return;
  112.     }
  113.     switch (gSound_detail_level) {
  114.     case 0:
  115.         engine_channel_count = 2;
  116.         car_channel_count = 2;
  117.         ped_channel_count = 3;
  118.         break;
  119.     case 1:
  120.         engine_channel_count = 2;
  121.         car_channel_count = 3;
  122.         ped_channel_count = 4;
  123.         break;
  124.     case 2:
  125.         engine_channel_count = 6;
  126.         car_channel_count = 4;
  127.         ped_channel_count = 5;
  128.         break;
  129.     default:
  130.         TELL_ME_IF_WE_PASS_THIS_WAY();
  131.     }
  132.     if (gDriver_outlet == NULL) {
  133.         gDriver_outlet = S3CreateOutlet(1, 1);
  134.         gIndexed_outlets[0] = gDriver_outlet;
  135.         if (gDriver_outlet == NULL) {
  136.             gSound_available = 0;
  137.             return;
  138.         }
  139.     }
  140.     if (!gMusic_outlet) {
  141.         gMusic_outlet = S3CreateOutlet(1, 1);
  142.         gIndexed_outlets[2] = gMusic_outlet;
  143.         gMusic_available = gMusic_outlet != 0;
  144.         DRS3SetOutletVolume(gMusic_outlet, 42 * gProgram_state.music_volume);
  145.     }
  146.     if (gSound_detail_level != gOld_sound_detail_level) {
  147.         if (gCar_outlet) {
  148.             S3ReleaseOutlet(gCar_outlet);
  149.             gCar_outlet = 0;
  150.         }
  151.         if (gPedestrians_outlet) {
  152.             S3ReleaseOutlet(gPedestrians_outlet);
  153.             gPedestrians_outlet = 0;
  154.         }
  155.         if (gEngine_outlet) {
  156.             S3ReleaseOutlet(gEngine_outlet);
  157.             gEngine_outlet = 0;
  158.         }
  159.         if (gEngine_outlet == NULL) {
  160.             gEngine_outlet = S3CreateOutlet(engine_channel_count, engine_channel_count);
  161.             gIndexed_outlets[1] = gEngine_outlet;
  162.             if (!gEngine_outlet) {
  163.                 gSound_available = 0;
  164.                 return;
  165.             }
  166.             DRS3SetOutletVolume(gEngine_outlet, 42 * gProgram_state.effects_volume);
  167.         }
  168.         if (gCar_outlet == NULL) {
  169.             gCar_outlet = S3CreateOutlet(car_channel_count, car_channel_count);
  170.             gIndexed_outlets[3] = gCar_outlet;
  171.             if (!gCar_outlet) {
  172.                 gSound_available = 0;
  173.                 return;
  174.             }
  175.             DRS3SetOutletVolume(gCar_outlet, 42 * gProgram_state.effects_volume);
  176.         }
  177.         if (gPedestrians_outlet == NULL) {
  178.             gPedestrians_outlet = S3CreateOutlet(ped_channel_count, ped_channel_count);
  179.             gIndexed_outlets[4] = gPedestrians_outlet;
  180.             if (!gPedestrians_outlet) {
  181.                 gSound_available = 0;
  182.                 return;
  183.             }
  184.             DRS3SetOutletVolume(gPedestrians_outlet, 42 * gProgram_state.effects_volume);
  185.         }
  186.     }
  187.     if (gEffects_outlet == NULL) {
  188.         gEffects_outlet = S3CreateOutlet(2, 2);
  189.         gIndexed_outlets[5] = gEffects_outlet;
  190.         if (!gEffects_outlet) {
  191.             gSound_available = 0;
  192.             return;
  193.         }
  194.         DRS3SetOutletVolume(gEffects_outlet, 42 * gProgram_state.effects_volume);
  195.     }
  196.     gOld_sound_detail_level = gSound_detail_level;
  197.     SetSoundVolumes();
  198. }
  199.  
  200. // IDA: tS3_sound_tag __usercall DRS3StartSound@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_sound_id pSound@<EDX>)
  201. tS3_sound_tag DRS3StartSound(tS3_outlet_ptr pOutlet, tS3_sound_id pSound) {
  202.     if (!gSound_enabled) {
  203.         return 0;
  204.     }
  205.     if (pSound != 1000 && (pSound < 3000 || pSound > 3007) && (pSound < 5300 || pSound > 5320)) {
  206.         PipeSingleSound(pOutlet, pSound, 0, 0, -1, 0);
  207.     }
  208.     return S3StartSound(pOutlet, pSound);
  209. }
  210.  
  211. // IDA: tS3_sound_tag __usercall DRS3StartSoundNoPiping@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_sound_id pSound@<EDX>)
  212. tS3_sound_tag DRS3StartSoundNoPiping(tS3_outlet_ptr pOutlet, tS3_sound_id pSound) {
  213.     if (!gSound_enabled) {
  214.         return 0;
  215.     }
  216.     return S3StartSound(pOutlet, pSound);
  217. }
  218.  
  219. // IDA: tS3_sound_tag __usercall DRS3StartSound2@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_sound_id pSound@<EDX>, tS3_repeats pRepeats@<EBX>, tS3_volume pLVolume@<ECX>, tS3_volume pRVolume, tS3_pitch pPitch, tS3_speed pSpeed)
  220. tS3_sound_tag DRS3StartSound2(tS3_outlet_ptr pOutlet, tS3_sound_id pSound, tS3_repeats pRepeats, tS3_volume pLVolume, tS3_volume pRVolume, tS3_pitch pPitch, tS3_speed pSpeed) {
  221.     LOG_TRACE("(%d, %d, %d, %d, %d, %d, %d)", pOutlet, pSound, pRepeats, pLVolume, pRVolume, pPitch, pSpeed);
  222.  
  223.     if (!gSound_enabled) {
  224.         return 0;
  225.     }
  226.     if (pOutlet != gMusic_outlet
  227.         && pSound != 1000
  228.         && (pSound < 3000 || pSound > 3007)
  229.         && (pSound < 5300 || pSound > 5320)
  230.         && (pLVolume || pRVolume)) {
  231.         PipeSingleSound(pOutlet, pSound, pLVolume, pRVolume, pPitch, 0);
  232.     }
  233.     return S3StartSound2(pOutlet, pSound, pRepeats, pLVolume, pRVolume, pPitch, pSpeed);
  234. }
  235.  
  236. // IDA: int __usercall DRS3ChangeVolume@<EAX>(tS3_sound_tag pSound_tag@<EAX>, tS3_volume pNew_volume@<EDX>)
  237. int DRS3ChangeVolume(tS3_sound_tag pSound_tag, tS3_volume pNew_volume) {
  238.     LOG_TRACE("(%d, %d)", pSound_tag, pNew_volume);
  239.  
  240.     if (gSound_enabled == 0) {
  241.         return 0;
  242.     }
  243.     return S3ChangeVolume(pSound_tag, pNew_volume);
  244. }
  245.  
  246. // IDA: int __usercall DRS3ChangeLRVolume@<EAX>(tS3_sound_tag pSound_tag@<EAX>, tS3_volume pNew_Lvolume@<EDX>, tS3_volume pNew_Rvolume@<EBX>)
  247. int DRS3ChangeLRVolume(tS3_sound_tag pSound_tag, tS3_volume pNew_Lvolume, tS3_volume pNew_Rvolume) {
  248.     LOG_TRACE("(%d, %d, %d)", pSound_tag, pNew_Lvolume, pNew_Rvolume);
  249.     NOT_IMPLEMENTED();
  250. }
  251.  
  252. // IDA: int __usercall DRS3ChangePitch@<EAX>(tS3_sound_tag pTag@<EAX>, tS3_pitch pNew_pitch@<EDX>)
  253. int DRS3ChangePitch(tS3_sound_tag pTag, tS3_pitch pNew_pitch) {
  254.     LOG_TRACE("(%d, %d)", pTag, pNew_pitch);
  255.     NOT_IMPLEMENTED();
  256. }
  257.  
  258. // IDA: int __usercall DRS3ChangeSpeed@<EAX>(tS3_sound_tag pTag@<EAX>, tS3_pitch pNew_speed@<EDX>)
  259. int DRS3ChangeSpeed(tS3_sound_tag pTag, tS3_pitch pNew_speed) {
  260.     LOG_TRACE("(%d, %d)", pTag, pNew_speed);
  261.     NOT_IMPLEMENTED();
  262.     return 0;
  263. }
  264.  
  265. // IDA: int __usercall DRS3ChangePitchSpeed@<EAX>(tS3_sound_tag pTag@<EAX>, tS3_pitch pNew_pitch@<EDX>)
  266. int DRS3ChangePitchSpeed(tS3_sound_tag pTag, tS3_pitch pNew_pitch) {
  267.     LOG_TRACE("(%d, %d)", pTag, pNew_pitch);
  268.  
  269.     if (!gSound_enabled) {
  270.         return 0;
  271.     }
  272.     return S3ChangePitchSpeed(pTag, pNew_pitch);
  273. }
  274.  
  275. // IDA: int __usercall DRS3StopSound@<EAX>(tS3_sound_tag pSound_tag@<EAX>)
  276. int DRS3StopSound(tS3_sound_tag pSound_tag) {
  277.     LOG_TRACE("(%d)", pSound_tag);
  278.  
  279.     if (!gSound_enabled) {
  280.         return 0;
  281.     }
  282.     return S3StopSound(pSound_tag);
  283. }
  284.  
  285. // IDA: int __usercall DRS3LoadSound@<EAX>(tS3_sound_id pThe_sound@<EAX>)
  286. int DRS3LoadSound(tS3_sound_id pThe_sound) {
  287.     LOG_TRACE("(%d)", pThe_sound);
  288.  
  289.     if (!gSound_enabled) {
  290.         return 0;
  291.     }
  292.     return S3LoadSample(pThe_sound);
  293. }
  294.  
  295. // IDA: int __usercall DRS3ReleaseSound@<EAX>(tS3_sound_id pThe_sound@<EAX>)
  296. int DRS3ReleaseSound(tS3_sound_id pThe_sound) {
  297.     LOG_TRACE("(%d)", pThe_sound);
  298.  
  299.     if (gSound_enabled == 0) {
  300.         return 0;
  301.     }
  302.     return S3ReleaseSound(pThe_sound);
  303. }
  304.  
  305. // IDA: void __cdecl DRS3Service()
  306. void DRS3Service(void) {
  307.     LOG_TRACE("()");
  308.  
  309.     if (gSound_enabled) {
  310.         if (gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) {
  311.             S3Service(1, 1);
  312.         } else {
  313.             S3Service(0, 1);
  314.         }
  315.     }
  316. }
  317.  
  318. // IDA: int __usercall DRS3OutletSoundsPlaying@<EAX>(tS3_outlet_ptr pOutlet@<EAX>)
  319. int DRS3OutletSoundsPlaying(tS3_outlet_ptr pOutlet) {
  320.     LOG_TRACE("(%d)", pOutlet);
  321.     NOT_IMPLEMENTED();
  322. }
  323.  
  324. // IDA: int __usercall DRS3SoundStillPlaying@<EAX>(tS3_sound_tag pSound_tag@<EAX>)
  325. int DRS3SoundStillPlaying(tS3_sound_tag pSound_tag) {
  326.     LOG_TRACE("(%d)", pSound_tag);
  327.  
  328.     return gSound_enabled && S3SoundStillPlaying(pSound_tag);
  329. }
  330.  
  331. // IDA: void __cdecl DRS3ShutDown()
  332. void DRS3ShutDown(void) {
  333.     LOG_TRACE("()");
  334.  
  335.     if (gSound_enabled) {
  336.         gSound_enabled = 0;
  337.         S3Shutdown();
  338.     }
  339. }
  340.  
  341. // IDA: int __usercall DRS3SetOutletVolume@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_volume pVolume@<EDX>)
  342. int DRS3SetOutletVolume(tS3_outlet_ptr pOutlet, tS3_volume pVolume) {
  343.     LOG_TRACE("(%d, %d)", pOutlet, pVolume);
  344.  
  345.     if (!gSound_enabled) {
  346.         return 0;
  347.     }
  348.     return S3SetOutletVolume(pOutlet, pVolume);
  349. }
  350.  
  351. // IDA: int __usercall DRS3OverallVolume@<EAX>(tS3_volume pVolume@<EAX>)
  352. int DRS3OverallVolume(tS3_volume pVolume) {
  353.     LOG_TRACE("(%d)", pVolume);
  354.     NOT_IMPLEMENTED();
  355. }
  356.  
  357. // IDA: int __usercall DRS3StopOutletSound@<EAX>(tS3_outlet_ptr pOutlet@<EAX>)
  358. int DRS3StopOutletSound(tS3_outlet_ptr pOutlet) {
  359.     if (!gSound_enabled) {
  360.         return 0;
  361.     }
  362.     return S3StopOutletSound(pOutlet);
  363. }
  364.  
  365. // IDA: int __cdecl DRS3StopAllOutletSounds()
  366. int DRS3StopAllOutletSounds(void) {
  367.     LOG_TRACE("()");
  368.  
  369.     if (gSound_enabled) {
  370.         S3StopAllOutletSounds();
  371.     }
  372.     return 0;
  373. }
  374.  
  375. // IDA: void __cdecl ToggleSoundEnable()
  376. void ToggleSoundEnable(void) {
  377.     LOG_TRACE("()");
  378.  
  379.     if (gSound_enabled) {
  380.         S3StopAllOutletSounds();
  381.         S3Disable();
  382.         gSound_enabled = 0;
  383.     } else {
  384.         S3Enable();
  385.         gSound_enabled = 1;
  386.     }
  387. }
  388.  
  389. // IDA: void __cdecl SoundService()
  390. void SoundService(void) {
  391.     //br_matrix34 mat; // Pierre-Marie Baty -- unused variable
  392.  
  393.     if (gSound_enabled && !gServicing_sound) {
  394.         gServicing_sound = 1;
  395.         gLast_sound_service = PDGetTotalTime();
  396.         if (gCDA_tag) {
  397.             if (!S3IsCDAPlaying2()) {
  398.                 StopMusic();
  399.                 StartMusic();
  400.             }
  401.         }
  402.         DRS3Service();
  403.         gServicing_sound = 0;
  404.     }
  405. }
  406.  
  407. // IDA: void __cdecl InitSoundSources()
  408. void InitSoundSources(void) {
  409.     int cat;
  410.     int car_count;
  411.     int i;
  412.     int toggle;
  413.     tCar_spec* the_car;
  414.     LOG_TRACE("()");
  415.  
  416.     toggle = 0;
  417.     if (!gSound_available) {
  418.         return;
  419.     }
  420.     if (!gSound_enabled) {
  421.         ToggleSoundEnable();
  422.         toggle = 1;
  423.     }
  424.     gCamera_position = *(br_vector3*)&gCamera_to_world.m[3][0];
  425.     gCamera_left.v[0] = gCamera_to_world.m[0][0] * -1.0;
  426.     gCamera_left.v[1] = gCamera_to_world.m[0][1] * -1.0;
  427.     gCamera_left.v[2] = gCamera_to_world.m[0][2] * -1.0;
  428.     S3BindListenerPositionBRender(&gCamera_position);
  429.     S3BindListenerVelocityBRender(&gCamera_velocity);
  430.     S3BindListenerLeftBRender(&gCamera_left);
  431.     if (!gSound_sources_inited) {
  432.         for (cat = eVehicle_self; cat <= eVehicle_rozzer; ++cat) {
  433.             if (cat) {
  434.                 car_count = GetCarCount(cat);
  435.             } else {
  436.                 car_count = 1;
  437.             }
  438.             for (i = 0; i < car_count; i++) {
  439.                 PossibleService();
  440.                 if (cat) {
  441.                     the_car = GetCarSpec(cat, i);
  442.                 } else {
  443.                     the_car = &gProgram_state.current_car;
  444.                 }
  445.                 if (the_car->driver == eDriver_local_human || gSound_detail_level == 2 || cat == eVehicle_rozzer) {
  446.                     the_car->sound_source = S3CreateSoundSourceBR(&the_car->pos, &the_car->velocity_bu_per_sec, gEngine_outlet);
  447.                     if (the_car->sound_source) {
  448.                         if (cat == eVehicle_rozzer) {
  449.                             S3BindAmbientSoundToOutlet(gEngine_outlet, 5350, the_car->sound_source, 250.0, 0, 0, 0, 0x10000, 0x10000);
  450.                         } else {
  451.                             S3BindAmbientSoundToOutlet(gEngine_outlet, the_car->engine_noises[0], the_car->sound_source, 250.0, 0, 0, 0, 0x10000, 0x10000);
  452.                         }
  453.                     }
  454.                 }
  455.             }
  456.         }
  457.         gSound_sources_inited = 1;
  458.     }
  459.     if (toggle) {
  460.         ToggleSoundEnable();
  461.     }
  462. }
  463.  
  464. // IDA: void __cdecl DisposeSoundSources()
  465. void DisposeSoundSources(void) {
  466.     int cat;
  467.     int car_count;
  468.     int i;
  469.     int toggle;
  470.     tCar_spec* the_car;
  471.     LOG_TRACE("()");
  472.  
  473.     toggle = 0;
  474.     if (gSound_available == 0) {
  475.         return;
  476.     }
  477.     if (!gSound_enabled) {
  478.         ToggleSoundEnable();
  479.         toggle = 1;
  480.     }
  481.     if (gSound_sources_inited) {
  482.         DRS3StopOutletSound(gEngine_outlet);
  483.         if (gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) {
  484.             S3Service(1, 0);
  485.         } else {
  486.             S3Service(0, 0);
  487.         }
  488.         for (cat = eVehicle_self; cat <= eVehicle_rozzer; cat++) {
  489.             if (cat) {
  490.                 car_count = GetCarCount(cat);
  491.             } else {
  492.                 car_count = 1;
  493.             }
  494.             for (i = 0; i < car_count; ++i) {
  495.                 if (cat) {
  496.                     the_car = GetCarSpec(cat, i);
  497.                 } else {
  498.                     the_car = &gProgram_state.current_car;
  499.                 }
  500.                 if (the_car->driver == eDriver_local_human || gSound_detail_level == 2 || cat == eVehicle_rozzer) {
  501.                     if (the_car->sound_source) {
  502.                         S3UpdateSoundSource(gEngine_outlet, -1, the_car->sound_source, 0.0f, 0, 0, 0, 0x10000, 0x10000);
  503.                         S3ReleaseSoundSource(the_car->sound_source);
  504.                     }
  505.                     the_car->sound_source = NULL;
  506.                 }
  507.             }
  508.         }
  509.         gSound_sources_inited = 0;
  510.     }
  511.     if (toggle) {
  512.         ToggleSoundEnable();
  513.     }
  514. }
  515.  
  516. // IDA: tS3_sound_tag __usercall DRS3StartSound3D@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_sound_id pSound@<EDX>, br_vector3 *pInitial_position@<EBX>, br_vector3 *pInitial_velocity@<ECX>, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed)
  517. tS3_sound_tag DRS3StartSound3D(tS3_outlet_ptr pOutlet, tS3_sound_id pSound, br_vector3* pInitial_position, br_vector3* pInitial_velocity, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed) {
  518.     //tS3_sound_tag tag; // Pierre-Marie Baty -- unused variable
  519.     LOG_TRACE("(%d, %d, %p, %p, %d, %d, %d, %d)", pOutlet, pSound, pInitial_position, pInitial_velocity, pRepeats, pVolume, pPitch, pSpeed);
  520.  
  521.     if (!gSound_enabled) {
  522.         return 0;
  523.     }
  524.     if (pVolume && pSound != 1000 && (pSound < 3000 || pSound > 3007) && (pSound < 5300 || pSound > 5320)) {
  525.         PipeSingleSound(pOutlet, pSound, pVolume, 0, pPitch, pInitial_position);
  526.     }
  527.     return S3StartSound3D(pOutlet, pSound, (tS3_vector3*)pInitial_position, (tS3_vector3*)pInitial_velocity, pRepeats, pVolume, pPitch, pSpeed);
  528. }
  529.  
  530. // IDA: tS3_sound_tag __usercall DRS3StartSoundFromSource3@<EAX>(tS3_sound_source_ptr pSource@<EAX>, tS3_sound_id pSound@<EDX>, tS3_repeats pRepeats@<EBX>, tS3_volume pVolume@<ECX>, tS3_pitch pPitch, tS3_speed pSpeed)
  531. tS3_sound_tag DRS3StartSoundFromSource3(tS3_sound_source_ptr pSource, tS3_sound_id pSound, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed) {
  532.     //tS3_sound_tag tag; // Pierre-Marie Baty -- unused variable
  533.     LOG_TRACE("(%d, %d, %d, %d, %d, %d)", pSource, pSound, pRepeats, pVolume, pPitch, pSpeed);
  534.     NOT_IMPLEMENTED();
  535. }
  536.  
  537. // IDA: tS3_sound_tag __usercall DRS3StartSoundFromSource@<EAX>(tS3_sound_source_ptr pSource@<EAX>, tS3_sound_id pSound@<EDX>)
  538. tS3_sound_tag DRS3StartSoundFromSource(tS3_sound_source_ptr pSource, tS3_sound_id pSound) {
  539.     //tS3_sound_tag tag; // Pierre-Marie Baty -- unused variable
  540.     LOG_TRACE("(%d, %d)", pSource, pSound);
  541.     NOT_IMPLEMENTED();
  542. }
  543.  
  544. // IDA: void __cdecl MungeEngineNoise()
  545. void MungeEngineNoise(void) {
  546.     tCar_spec* the_car;
  547.     tU32 pitch;
  548.     int vol;
  549.     int cat;
  550.     int car_count;
  551.     int i;
  552.     int stop_all;
  553.     int type_of_engine_noise;
  554.     //tS3_sound_id engine_noise; // Pierre-Marie Baty -- unused variable
  555.  
  556.     // added by dethrace
  557.     tU32 frame_period;
  558.     frame_period = gFrame_period;
  559.  
  560. #ifdef DETHRACE_FIX_BUGS
  561.     // At framerates higher than 30, `gCamera_velocity` is not stable enough and causes the player car audio to stumble
  562.     // as the pitch shifts up and down while applying doppler effect in `S3Calculate3D`.
  563.     // We avoid the issue by only updating the engine sounds every MUNGE_ENGINE_INTERVAL ms
  564.     static tU32 dethrace_last_executed = 0;
  565.  
  566.     tU32 now = GetTotalTime();
  567.     if (now - dethrace_last_executed < MUNGE_ENGINE_INTERVAL) {
  568.         return;
  569.     }
  570.     frame_period = now - dethrace_last_executed;
  571.     dethrace_last_executed = now;
  572. #endif
  573.  
  574.     type_of_engine_noise = 0;
  575.     if (gSound_available == 0 || gProgram_state.racing == 0) {
  576.         return;
  577.     }
  578.  
  579.     BrVector3Copy(&gCamera_position, (br_vector3*)&gCamera_to_world.m[3][0]);
  580.     BrVector3Negate(&gCamera_left, (br_vector3*)&gCamera_to_world.m[0][0]);
  581.     BrVector3Sub(&gCamera_velocity, &gCamera_position, &gOld_camera_position);
  582.     if (frame_period) {
  583.         BrVector3InvScale(&gCamera_velocity, &gCamera_velocity, ((float)frame_period / 1000.0f));
  584.     } else {
  585.         BrVector3Set(&gCamera_velocity, 0.0f, 0.0f, 0.0f);
  586.     }
  587.     BrVector3Copy(&gOld_camera_position, &gCamera_position);
  588.     stop_all = (gAction_replay_mode && (fabsf(GetReplayRate()) > 1.0f || GetReplayRate() == 0.0f)) || gFaded_palette || gPalette_fade_time;
  589.     for (cat = eVehicle_self; cat <= eVehicle_rozzer; cat++) {
  590.         if (cat) {
  591.             car_count = GetCarCount(cat);
  592.         } else {
  593.             car_count = 1;
  594.         }
  595.         for (i = 0; i < car_count; i++) {
  596.             if (cat) {
  597.                 the_car = GetCarSpec(cat, i);
  598.             } else {
  599.                 the_car = &gProgram_state.current_car;
  600.             }
  601.             if (the_car->driver == eDriver_local_human || gSound_detail_level == 2 || cat == eVehicle_rozzer) {
  602.                 if (stop_all || !the_car->active || the_car->knackered || (cat == eVehicle_rozzer && BrVector3LengthSquared(&the_car->v) < 0.0001f)) {
  603.                     vol = 0;
  604.                     pitch = 0x10000;
  605.                 } else {
  606.                     BrVector3InvScale(&the_car->velocity_bu_per_sec, &the_car->v, WORLD_SCALE);
  607.                     if (cat == eVehicle_rozzer) {
  608.                         vol = 255;
  609.                         pitch = 0x10000;
  610.                     } else {
  611.                         if (the_car->last_special_volume) {
  612.                             type_of_engine_noise = the_car->last_special_volume->engine_noise_index;
  613.                         }
  614.                         pitch = the_car->revs * 10.0f + 40960.0f;
  615.                         if (gAction_replay_mode) {
  616.                             pitch = fabsf(GetReplayRate()) * pitch;
  617.                         }
  618.                         if (type_of_engine_noise == 1) {
  619.                             pitch = pitch * 0.75f;
  620.                         } else if (type_of_engine_noise == 2) {
  621.                             pitch = pitch * 0.55f;
  622.                         }
  623.  
  624.                         pitch = MAX(pitch, 4096);
  625.                         pitch = MIN(pitch, 131072);
  626.  
  627.                         vol = the_car->revs * 0.001f + 64.0f;
  628.                         if (type_of_engine_noise == 1) {
  629.                             vol = vol * 5.0f;
  630.                         } else if (type_of_engine_noise == 2) {
  631.                             vol = vol * 2.0f;
  632.                         } else {
  633.                             vol = vol * 2.5f;
  634.                         }
  635.                         vol = MIN(vol, 255);
  636.                     }
  637.                 }
  638.                 S3UpdateSoundSource(gEngine_outlet, -1, the_car->sound_source, gAction_replay_mode == 0 ? 250.0f : 300.0f, 0, 0, vol, pitch, 0x10000);
  639.             }
  640.         }
  641.     }
  642.     SoundService();
  643. }
  644.  
  645. // IDA: void __cdecl SetSoundVolumes()
  646. void SetSoundVolumes(void) {
  647.  
  648.     if (!gSound_enabled) {
  649.         return;
  650.     }
  651.     if (gEffects_outlet != NULL) {
  652.         DRS3SetOutletVolume(gEffects_outlet, 42 * gProgram_state.effects_volume);
  653.     }
  654.     DRS3SetOutletVolume(gCar_outlet, 42 * gProgram_state.effects_volume);
  655.     DRS3SetOutletVolume(gEngine_outlet, 42 * gProgram_state.effects_volume);
  656.     DRS3SetOutletVolume(gDriver_outlet, 42 * gProgram_state.effects_volume);
  657.     DRS3SetOutletVolume(gPedestrians_outlet, 42 * gProgram_state.effects_volume);
  658.     DRS3SetOutletVolume(gMusic_outlet, 42 * gProgram_state.music_volume);
  659. }
  660.  
  661. // IDA: tS3_outlet_ptr __usercall GetOutletFromIndex@<EAX>(int pIndex@<EAX>)
  662. tS3_outlet_ptr GetOutletFromIndex(int pIndex) {
  663.     LOG_TRACE("(%d)", pIndex);
  664.  
  665.     return gIndexed_outlets[pIndex];
  666. }
  667.  
  668. // IDA: int __usercall GetIndexFromOutlet@<EAX>(tS3_outlet_ptr pOutlet@<EAX>)
  669. int GetIndexFromOutlet(tS3_outlet_ptr pOutlet) {
  670.     int i;
  671.     LOG_TRACE("(%d)", pOutlet);
  672.  
  673.     for (i = 0; i < COUNT_OF(gIndexed_outlets); i++) {
  674.         if (gIndexed_outlets[i] == pOutlet) {
  675.             return i;
  676.         }
  677.     }
  678.     return 0;
  679. }
  680.  
  681. // IDA: int __usercall DRS3StartCDA@<EAX>(tS3_sound_id pCDA_id@<EAX>)
  682. int DRS3StartCDA(tS3_sound_id pCDA_id) {
  683.     LOG_TRACE("(%d)", pCDA_id);
  684.     NOT_IMPLEMENTED();
  685. }
  686.  
  687. // IDA: int __cdecl DRS3StopCDA()
  688. int DRS3StopCDA(void) {
  689.     LOG_TRACE("()");
  690.     NOT_IMPLEMENTED();
  691. }
  692.  
  693. // IDA: void __cdecl StartMusic()
  694. void StartMusic(void) {
  695. }
  696.  
  697. // IDA: void __cdecl StopMusic()
  698. void StopMusic(void) {
  699. }
  700.