Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  */
  7. /*
  8.  * Digital audio support
  9.  * Library-independent stub for dynamic selection of sound system
  10.  */
  11.  
  12. #include "dxxerror.h"
  13. #include "vecmat.h"
  14. #include "piggy.h"
  15. #include "config.h"
  16. #include "digi.h"
  17. #include "sounds.h"
  18. #include "console.h"
  19. #include "rbaudio.h"
  20. #include "jukebox.h"
  21. #include "args.h"
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <digi.h>
  26. #include <digi_audio.h>
  27.  
  28. #if DXX_USE_SDLMIXER
  29. #include <digi_mixer.h>
  30. #include <SDL_mixer.h>
  31. #endif
  32. #ifdef _WIN32
  33. #include "hmp.h"
  34. #endif
  35.  
  36. namespace dcx {
  37.  
  38. int digi_volume = SOUND_MAX_VOLUME;
  39.  
  40. /* The values for these three defines are arbitrary and can be changed,
  41.  * provided that they remain unique with respect to each other.
  42.  */
  43. #define DXX_STS_MIXER_WITH_POINTER      0
  44. #define DXX_STS_MIXER_WITH_COPY 1
  45. #define DXX_STS_NO_MIXER        2
  46.  
  47. #if DXX_USE_SDLMIXER
  48. #ifndef DXX_SOUND_TABLE_STYLE
  49. #ifdef __PIE__
  50. /* PIE -> paranoid checks
  51.  * No PIE -> prefer speed
  52.  */
  53. #define DXX_SOUND_TABLE_STYLE   DXX_STS_MIXER_WITH_POINTER
  54. #else
  55. #define DXX_SOUND_TABLE_STYLE   DXX_STS_MIXER_WITH_COPY
  56. #endif
  57. #endif
  58. #else
  59. #define DXX_SOUND_TABLE_STYLE   DXX_STS_NO_MIXER
  60. #endif
  61.  
  62. /* Sound system function pointers */
  63.  
  64. namespace {
  65.  
  66. struct sound_function_table_t
  67. {
  68.         int  (*init)();
  69.         void (*close)();
  70. #ifndef RELEASE
  71.         void (*reset)();
  72. #endif
  73.         void (*set_channel_volume)(int, int);
  74.         void (*set_channel_pan)(int, int);
  75.         int  (*start_sound)(short, fix, int, int, int, int, sound_object *);
  76.         void (*stop_sound)(int);
  77.         void (*end_sound)(int);
  78.         int  (*is_channel_playing)(int);
  79.         void (*stop_all_channels)();
  80.         void (*set_digi_volume)(int);
  81. };
  82.  
  83. #if DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_POINTER
  84. [[noreturn]]
  85. __attribute_cold
  86. void report_invalid_table()
  87. {
  88.         /* Out of line due to length of generated code */
  89.         throw std::logic_error("invalid sound table pointer");
  90. }
  91. #endif
  92.  
  93. }
  94.  
  95. }
  96.  
  97. #if DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_POINTER
  98. namespace dsx
  99. #else
  100. namespace dcx
  101. #endif
  102. {
  103.  
  104. namespace {
  105.  
  106. class sound_function_pointers_t
  107. {
  108. #if DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_COPY
  109.         sound_function_table_t table;
  110. #elif DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_POINTER
  111.         const sound_function_table_t *table;
  112. #endif
  113. public:
  114.         inline const sound_function_table_t *operator->();
  115.         inline sound_function_pointers_t &operator=(const sound_function_table_t &t);
  116. };
  117.  
  118. #if DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_COPY
  119. const sound_function_table_t *sound_function_pointers_t::operator->()
  120. {
  121.         return &table;
  122. }
  123.  
  124. sound_function_pointers_t &sound_function_pointers_t::operator=(const sound_function_table_t &t)
  125. {
  126.         table = t;
  127.         return *this;
  128. }
  129. #elif DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_POINTER
  130.  
  131. sound_function_pointers_t &sound_function_pointers_t::operator=(const sound_function_table_t &t)
  132. {
  133.         table = &t;
  134.         /* Trap bad initial assignment */
  135.         operator->();
  136.         return *this;
  137. }
  138. #elif DXX_SOUND_TABLE_STYLE == DXX_STS_NO_MIXER
  139. const sound_function_table_t *sound_function_pointers_t::operator->()
  140. {
  141.         return &digi_audio_table;
  142. }
  143.  
  144. sound_function_pointers_t &sound_function_pointers_t::operator=(const sound_function_table_t &)
  145. {
  146.         return *this;
  147. }
  148. #endif
  149.  
  150. }
  151.  
  152. static sound_function_pointers_t fptr;
  153.  
  154. }
  155.  
  156. namespace dsx {
  157.  
  158. namespace {
  159.  
  160.         /* Some of the functions are in dsx, so the definition and
  161.          * initializer must be in dsx.
  162.          */
  163. #if DXX_USE_SDLMIXER
  164. constexpr sound_function_table_t digi_mixer_table{
  165.         &digi_mixer_init,
  166.         &digi_mixer_close,
  167. #ifndef RELEASE
  168.         &digi_mixer_reset,
  169. #endif
  170.         &digi_mixer_set_channel_volume,
  171.         &digi_mixer_set_channel_pan,
  172.         &digi_mixer_start_sound,
  173.         &digi_mixer_stop_sound,
  174.         &digi_mixer_end_sound,
  175.         &digi_mixer_is_channel_playing,
  176.         &digi_mixer_stop_all_channels,
  177.         &digi_mixer_set_digi_volume,
  178. };
  179. #endif
  180.  
  181. constexpr sound_function_table_t digi_audio_table{
  182.         &digi_audio_init,
  183.         &digi_audio_close,
  184. #ifndef RELEASE
  185.         &digi_audio_reset,
  186. #endif
  187.         &digi_audio_set_channel_volume,
  188.         &digi_audio_set_channel_pan,
  189.         &digi_audio_start_sound,
  190.         &digi_audio_stop_sound,
  191.         &digi_audio_end_sound,
  192.         &digi_audio_is_channel_playing,
  193.         &digi_audio_stop_all_channels,
  194.         &digi_audio_set_digi_volume,
  195. };
  196.  
  197. #if DXX_SOUND_TABLE_STYLE == DXX_STS_MIXER_WITH_POINTER
  198. const sound_function_table_t *sound_function_pointers_t::operator->()
  199. {
  200.         if (table != &digi_audio_table && table != &digi_mixer_table)
  201.                 report_invalid_table();
  202.         return table;
  203. }
  204. #endif
  205.  
  206. }
  207.  
  208. void digi_select_system()
  209. {
  210. #if DXX_USE_SDLMIXER
  211.         if (!CGameArg.SndDisableSdlMixer)
  212.         {
  213.                 const auto vl = Mix_Linked_Version();
  214.                 con_printf(CON_NORMAL, "Using SDL_mixer library v%u.%u.%u", vl->major, vl->minor, vl->patch);
  215.                 fptr = digi_mixer_table;
  216.                 return;
  217.         }
  218. #endif
  219.         con_puts(CON_NORMAL,"Using plain old SDL audio");
  220.                 fptr = digi_audio_table;
  221. }
  222.  
  223. /* Common digi functions */
  224. #if defined(DXX_BUILD_DESCENT_I)
  225. int digi_sample_rate = SAMPLE_RATE_11K;
  226. #endif
  227.  
  228. /* Stub functions */
  229.  
  230. int  digi_init()
  231. {
  232.         digi_init_sounds();
  233.         return fptr->init();
  234. }
  235.  
  236. void digi_close() { fptr->close(); }
  237. #ifndef RELEASE
  238. void digi_reset() { fptr->reset(); }
  239. #endif
  240.  
  241. void digi_set_channel_volume(int channel, int volume) { fptr->set_channel_volume(channel, volume); }
  242. void digi_set_channel_pan(int channel, int pan) { fptr->set_channel_pan(channel, pan); }
  243.  
  244. int  digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, sound_object *soundobj)
  245. {
  246.         return fptr->start_sound(soundnum, volume, pan, looping, loop_start, loop_end, soundobj);
  247. }
  248.  
  249. void digi_stop_sound(int channel) { fptr->stop_sound(channel); }
  250. void digi_end_sound(int channel) { fptr->end_sound(channel); }
  251.  
  252. int  digi_is_channel_playing(int channel) { return fptr->is_channel_playing(channel); }
  253. void digi_stop_all_channels() { fptr->stop_all_channels(); }
  254. void digi_set_digi_volume(int dvolume) { fptr->set_digi_volume(dvolume); }
  255.  
  256. #ifdef _WIN32
  257. // Windows native-MIDI stuff.
  258. static uint8_t digi_win32_midi_song_playing;
  259. static uint8_t already_playing;
  260. static std::unique_ptr<hmp_file> cur_hmp;
  261.  
  262. void digi_win32_set_midi_volume( int mvolume )
  263. {
  264.         hmp_setvolume(cur_hmp.get(), mvolume*MIDI_VOLUME_SCALE/8);
  265. }
  266.  
  267. int digi_win32_play_midi_song( const char * filename, int loop )
  268. {
  269.         if (!already_playing)
  270.         {
  271.                 hmp_reset();
  272.                 already_playing = 1;
  273.         }
  274.         digi_win32_stop_midi_song();
  275.  
  276.         if (filename == NULL)
  277.                 return 0;
  278.  
  279.         if ((cur_hmp = hmp_open(filename)))
  280.         {
  281.                 /*
  282.                  * FIXME: to be implemented as soon as we have some kind or checksum function - replacement for ugly hack in hmp.c for descent.hmp
  283.                  * if (***filesize check*** && ***CRC32 or MD5 check***)
  284.                  *      (((*cur_hmp).trks)[1]).data[6] = 0x6C;
  285.                  */
  286.                 if (hmp_play(cur_hmp.get(),loop) != 0)
  287.                         return 0;       // error
  288.                 digi_win32_midi_song_playing = 1;
  289.                 digi_win32_set_midi_volume(GameCfg.MusicVolume);
  290.                 return 1;
  291.         }
  292.  
  293.         return 0;
  294. }
  295.  
  296. void digi_win32_pause_midi_song()
  297. {
  298.         hmp_pause(cur_hmp.get());
  299. }
  300.  
  301. void digi_win32_resume_midi_song()
  302. {
  303.         hmp_resume(cur_hmp.get());
  304. }
  305.  
  306. void digi_win32_stop_midi_song()
  307. {
  308.         if (!digi_win32_midi_song_playing)
  309.                 return;
  310.         digi_win32_midi_song_playing = 0;
  311.         cur_hmp.reset();
  312.         hmp_reset();
  313. }
  314. #endif
  315.  
  316. }
  317.