]> git.lizzy.rs Git - nothing.git/blob - src/game/sound_samples.c
Merge pull request #485 from tsoding/476
[nothing.git] / src / game / sound_samples.c
1 #include <SDL2/SDL.h>
2 #include <SDL2/SDL_mixer.h>
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include "math/pi.h"
8 #include "sound_samples.h"
9 #include "system/error.h"
10 #include "system/log.h"
11 #include "system/lt.h"
12 #include "system/nth_alloc.h"
13
14 struct Sound_samples
15 {
16     Lt *lt;
17     Mix_Chunk **samples;
18     size_t samples_count;
19     int paused;
20 };
21
22 static int mix_get_free_channel(void)
23 {
24     for (int i = 0; i < MIX_CHANNELS; ++i) {
25         if (!Mix_Playing(i)) {
26             return i;
27         }
28     }
29
30     return -1;
31 }
32
33 Sound_samples *create_sound_samples(const char *sample_files[],
34                                       size_t sample_files_count)
35 {
36     assert(sample_files);
37     assert(sample_files_count > 0);
38
39     Lt *lt = create_lt();
40     if (lt == NULL) {
41         return NULL;
42     }
43
44     Sound_samples *sound_samples = PUSH_LT(lt, nth_alloc(sizeof(Sound_samples)), free);
45     if (sound_samples == NULL) {
46         throw_error(ERROR_TYPE_LIBC);
47         RETURN_LT(lt, NULL);
48     }
49
50     sound_samples->samples = PUSH_LT(
51         lt,
52         nth_alloc(sizeof(Mix_Chunk*) * sample_files_count),
53         free);
54     if (sound_samples->samples == NULL) {
55         throw_error(ERROR_TYPE_LIBC);
56         RETURN_LT(lt, NULL);
57     }
58
59     for (size_t i = 0; i < sample_files_count; ++i) {
60         sound_samples->samples[i] = PUSH_LT(
61             lt,
62             Mix_LoadWAV(sample_files[i]),
63             Mix_FreeChunk);
64         if (sound_samples->samples[i] == NULL) {
65             throw_error(ERROR_TYPE_SDL2_MIXER);
66             RETURN_LT(lt, NULL);
67         }
68     }
69
70     sound_samples->samples_count = sample_files_count;
71     sound_samples->paused = 0;
72
73     sound_samples->lt = lt;
74
75     return sound_samples;
76 }
77
78 void destroy_sound_samples(Sound_samples *sound_samples)
79 {
80     assert(sound_samples);
81     RETURN_LT0(sound_samples->lt);
82 }
83
84 int sound_samples_play_sound(Sound_samples *sound_samples,
85                             size_t sound_index,
86                             int loops)
87 {
88     assert(sound_samples);
89
90     if (sound_index < sound_samples->samples_count) {
91         const int free_channel = mix_get_free_channel();
92
93         log_info("Found free channel: %d\n", free_channel);
94
95         if (free_channel >= 0) {
96             return Mix_PlayChannel(free_channel, sound_samples->samples[sound_index], loops);
97         }
98     }
99
100     return 0;
101 }
102
103 int sound_samples_toggle_pause(Sound_samples *sound_samples)
104 {
105     assert(sound_samples);
106
107     if (sound_samples->paused) {
108         Mix_Resume(-1);
109     } else {
110         Mix_Pause(-1);
111     }
112
113     sound_samples->paused = !sound_samples->paused;
114
115     return 0;
116 }