4 #include "misc.h" // int2host
5 #include "memory.h" // M_lock M_unlock
6 #include "files.h" // F_findres
10 #include <SDL_mixer.h>
13 #define TAG_MIX1 0x4d495831
17 Uint32 len
; // length [bytes]
18 Uint32 rate
; // freq [Hz]
19 Uint32 lstart
; // loop start offset [bytes]
20 Uint32 llen
; // loop length [bytes]
21 Uint8 data
[]; // sound data
30 short snd_vol
; // public 0..128
32 static int devfreq
= MIX_DEFAULT_FREQUENCY
;
33 static Uint32 devformat
= AUDIO_S16SYS
; // MIX_DEFAULT_FORMAT
34 static int devchannels
= 1; // MIX_DEFAULT_CHANNELS;
35 static int devchunksize
= 1024;
36 static int devchunkchannels
= 8;
46 void S_initmusic (void) {
50 void S_donemusic (void) {
54 void S_startmusic (int time
) {
58 void S_stopmusic (void) {
62 void S_volumemusic (int v
) {
66 void F_loadmus (char n
[8]) {
70 void F_freemus (void) {
74 void S_updatemusic (void) {
82 logo("S_init: initialize sound\n");
83 if (SDL_InitSubSystem(SDL_INIT_AUDIO
) == 0) {
84 if (Mix_OpenAudio(devfreq
, devformat
, devchannels
, devchunksize
) == 0) {
85 Mix_AllocateChannels(devchunkchannels
);
88 logo("S_init: Mix_OpenAudio: %s\n", Mix_GetError());
91 logo("S_init: SDL_InitSubSytem: %s\n", SDL_GetError());
95 static Mix_Chunk
*convert_this (int rate
, const Uint8
*buf
, int len
) {
98 if (SDL_BuildAudioCVT(&cvt
, AUDIO_S8
, 1, rate
, devformat
, devchannels
, devfreq
) != -1) {
99 int maxlen
= len
* cvt
.len_mult
;
100 Uint8
*maxbuf
= malloc(maxlen
);
101 if (maxbuf
!= NULL
) {
102 memcpy(maxbuf
, buf
, len
);
105 if (SDL_ConvertAudio(&cvt
) == 0) {
106 c
= malloc(sizeof(Mix_Chunk
));
110 c
->alen
= len
* cvt
.len_ratio
;
111 c
->volume
= MIX_MAX_VOLUME
;
123 // TODO load raw sounds with voices
125 snd_t
*S_get (int id
) {
129 struct dmi
*snd
= M_lock(id
);
130 struct sound
*res
= NULL
;
132 int rlen
= F_getreslen(id
);
134 Uint32 len
= int2host(snd
->len
);
135 Uint32 rate
= int2host(snd
->rate
);
136 Uint32 lstart
= int2host(snd
->lstart
);
137 Uint32 llen
= int2host(snd
->llen
);
138 if (len
<= rlen
- 8 && lstart
+ llen
<= rlen
- 16) {
139 Mix_Chunk
*c
= convert_this(rate
, snd
->data
, len
);
141 res
= malloc(sizeof(struct sound
));
143 res
->base
.tag
= TAG_MIX1
;
151 logo("S_get(%i): invalid header {len=%u:rate=%u:lstart=%u:llen=%u:rlen=%i}\n", id
, len
, rate
, lstart
, llen
, rlen
);
154 logo("S_load(%i): too short\n", id
);
158 logo("S_load(%i): not found\n", id
);
163 snd_t
*S_load (const char name
[8]) {
164 int id
= F_findres(name
);
168 short S_play (snd_t
*s
, short c
, short v
) {
169 assert(c
>= 0 && c
<= 8);
170 assert(v
>= 0 && v
<= 255);
174 struct sound
*snd
= (struct sound
*)s
;
175 assert(snd
->base
.tag
== TAG_MIX1
);
176 // TODO care about global volume level
177 snd
->c
->volume
= v
* MIX_MAX_VOLUME
/ 255;
178 channel
= Mix_PlayChannel(c
<= 0 ? -1 : c
- 1, snd
->c
, 0);
179 channel
= channel
== -1 ? 0 : channel
+ 1;
185 void S_stop (short c
) {
186 assert(c
>= 0 && c
<= 8);
189 Mix_HaltChannel(c
- 1);
194 void S_volume (int v
) {
195 snd_vol
= min(max(v
, 0), 128);
197 // TODO change relativelly for every channel
198 Mix_Volume(-1, v
* MIX_MAX_VOLUME
/ 128);
204 while (Mix_Playing(-1) > 0) {
213 Mix_AllocateChannels(0);
215 SDL_QuitSubSystem(SDL_INIT_AUDIO
);