sound.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include <allegro5/allegro_audio.h>
  2. #include <allegro5/allegro_acodec.h>
  3. #include "sound.h"
  4. #include "mem.h"
  5. #include "store.h"
  6. struct Sound_;
  7. typedef struct Sound_ Sound;
  8. struct Music_;
  9. typedef struct Music_ Music;
  10. struct Audio_;
  11. typedef struct Audio_ Audio;
  12. /** Wraper structure around an allegro sample. */
  13. struct Sound_ {
  14. ALLEGRO_SAMPLE * handle;
  15. ALLEGRO_SAMPLE_ID id;
  16. };
  17. /** Wrapper structure around an allegro sound stream. */
  18. struct Music_ {
  19. ALLEGRO_AUDIO_STREAM * handle;
  20. };
  21. #define AUDIO_PLAYING_SAMPLES_MAX 64
  22. #define AUDIO_VOICES 8
  23. /**
  24. * Wraps around the Allegro sound system, and put severything in one handy
  25. * struct.
  26. */
  27. struct Audio_ {
  28. BOOL ok;
  29. ALLEGRO_MIXER * mixer;
  30. ALLEGRO_VOICE * voice;
  31. ALLEGRO_AUDIO_STREAM * stream;
  32. int stream_id;
  33. ALLEGRO_SAMPLE_ID playing[AUDIO_PLAYING_SAMPLES_MAX];
  34. int playing_id[AUDIO_PLAYING_SAMPLES_MAX];
  35. int playing_last;
  36. };
  37. /* The "global" audio state. */
  38. static Audio * audio_state;
  39. #ifndef SOUND_SAMPLES
  40. #define SOUND_SAMPLES 16
  41. #endif
  42. #define AUDIO_RATE 44100
  43. #define AUDIO_DEPTH ALLEGRO_AUDIO_DEPTH_INT16
  44. #define AUDIO_CHANNELS ALLEGRO_CHANNEL_CONF_2
  45. /* Call this when the use of audio is no longer needed. */
  46. BOOL audio_done() {
  47. if (!audio_state) {
  48. return FALSE;
  49. }
  50. al_stop_samples();
  51. if (audio_state->stream) {
  52. al_detach_audio_stream(audio_state->stream);
  53. }
  54. if (audio_state->mixer) {
  55. al_detach_mixer(audio_state->mixer);
  56. al_destroy_mixer(audio_state->mixer);
  57. }
  58. if (audio_state->voice) {
  59. al_destroy_voice(audio_state->voice);
  60. audio_state->voice = NULL;
  61. }
  62. mem_free(audio_state);
  63. al_uninstall_audio();
  64. return TRUE;
  65. }
  66. /** Call this to alloate space for the audio system. */
  67. Audio * audio_alloc(void) {
  68. return STRUCT_ALLOC(Audio);
  69. }
  70. int audio_playing_samples_max() {
  71. return AUDIO_PLAYING_SAMPLES_MAX;
  72. }
  73. /** Call this to start up the audio system. */
  74. BOOL audio_init() {
  75. int index;
  76. if(!al_install_audio()) return FALSE;
  77. if(!al_init_acodec_addon()) return FALSE;
  78. audio_state = audio_alloc();
  79. if (!audio_state) return FALSE;
  80. audio_state->mixer =
  81. al_create_mixer(AUDIO_RATE, AUDIO_DEPTH, AUDIO_CHANNELS);
  82. audio_state->voice =
  83. al_create_voice(AUDIO_RATE, AUDIO_DEPTH, AUDIO_CHANNELS);
  84. al_attach_mixer_to_voice(audio_state->mixer, audio_state->voice);
  85. al_set_default_mixer(audio_state->mixer);
  86. al_reserve_samples(SOUND_SAMPLES);
  87. audio_state->stream = NULL;
  88. audio_state->stream_id = -1;
  89. for (index = 0; index < AUDIO_PLAYING_SAMPLES_MAX; index++) {
  90. audio_state->playing_id[index] = -1;
  91. }
  92. audio_state->ok = TRUE;
  93. return TRUE;
  94. }
  95. /** Returns true if sound can be played, false if not. */
  96. BOOL audio_ok(void) {
  97. return audio_state && audio_state->ok;
  98. }
  99. #ifndef MUSIC_BUFFERS
  100. #define MUSIC_BUFFERS 2
  101. #endif
  102. #ifndef MUSIC_BUFSIZE
  103. #define MUSIC_BUFSIZE 2048
  104. #endif
  105. /* Set the music with the given index as the active usic.
  106. If the index is negative, sets no music as active. */
  107. BOOL audio_set_music(int store_id) {
  108. double length;
  109. ALLEGRO_AUDIO_STREAM * stream;
  110. if (!audio_ok()) return FALSE;
  111. if (store_id < 0) {
  112. if(audio_state->stream) {
  113. al_detach_audio_stream(audio_state->stream);
  114. }
  115. audio_state->stream = NULL;
  116. audio_state->stream_id = -1;
  117. return TRUE;
  118. }
  119. stream = store_get_audio_stream(store_id);
  120. if (!stream) {
  121. return FALSE;
  122. }
  123. audio_state->stream = stream;
  124. /* Automaticallly loop the music over it's whole length. */
  125. length = al_get_audio_stream_length_secs(audio_state->stream);
  126. if (length > 0.0) {
  127. al_set_audio_stream_loop_secs(audio_state->stream, 0.0, length);
  128. al_set_audio_stream_playmode(audio_state->stream, ALLEGRO_PLAYMODE_LOOP);
  129. }
  130. al_attach_audio_stream_to_mixer(audio_state->stream, audio_state->mixer);
  131. return TRUE;
  132. }
  133. BOOL audio_play_music() {
  134. if (!audio_ok()) return FALSE;
  135. if(!audio_state->stream) return FALSE;
  136. return al_set_audio_stream_playing(audio_state->stream, TRUE);
  137. }
  138. BOOL audio_stop_music() {
  139. if (!audio_ok()) return FALSE;
  140. if(!audio_state->stream) return FALSE;
  141. return al_set_audio_stream_playing(audio_state->stream, FALSE);
  142. }
  143. BOOL audio_music_playing_p() {
  144. if (!audio_ok()) return FALSE;
  145. if(!audio_state->stream) return FALSE;
  146. return al_get_audio_stream_playing(audio_state->stream);
  147. }
  148. int audio_playing_music_id() {
  149. if (!audio_ok()) return -1;
  150. if(!audio_state->stream) return -1;
  151. return audio_state->stream_id;
  152. }
  153. int audio_play_sound_ex
  154. (int store_id, float gain, float pan, float speed, BOOL loop) {
  155. int play_id;
  156. ALLEGRO_SAMPLE * sample;
  157. ALLEGRO_PLAYMODE mode =
  158. (loop ? ALLEGRO_PLAYMODE_LOOP : ALLEGRO_PLAYMODE_ONCE);
  159. if (!audio_ok()) return -2;
  160. sample = store_get_sample(store_id);
  161. if (!sample) return -1;
  162. play_id = audio_state->playing_last;
  163. audio_state->playing_last++;
  164. /* Work in ring buffer style. */
  165. if (audio_state->playing_last >= AUDIO_PLAYING_SAMPLES_MAX) {
  166. audio_state->playing_last = 0;
  167. }
  168. al_play_sample(sample, gain, pan, speed, mode,
  169. audio_state->playing + play_id);
  170. audio_state->playing_id[play_id] = store_id;
  171. return play_id;
  172. }
  173. void audio_stop_all_sounds() {
  174. al_stop_samples();
  175. /* reset ring buffer pointer */
  176. audio_state->playing_last = 0;
  177. }
  178. /** Plays the sound once only with default parameters. */
  179. int audio_play_sound(int sample_id) {
  180. return audio_play_sound_ex(sample_id, 1.0, 0.0, 1.0, FALSE);
  181. }
  182. /*
  183. Stops the sound with the given play id from playing. Doesn't work if
  184. the integer handle is stale, but thesoun sould have stopped by itself then.
  185. */
  186. BOOL audio_stop_sound(int play_id) {
  187. if (!audio_ok()) return FALSE;
  188. if (play_id < 0) return FALSE;
  189. if (play_id >= AUDIO_PLAYING_SAMPLES_MAX) return FALSE;
  190. al_stop_sample(audio_state->playing + play_id);
  191. return TRUE;
  192. }