ddacddf2497ff55556609a01a2303242de686649
4 #include "misc.h" // int2host
5 #include "memory.h" // M_lock M_unlock
6 #include "files.h" // F_findres
10 #include "SDL_mixer.h"
14 #define TAG_MIX1 0x4d495831
18 Uint32 len
; // length [bytes]
19 Uint32 rate
; // freq [Hz]
20 Uint32 lstart
; // loop start offset [bytes]
21 Uint32 llen
; // loop length [bytes]
22 Uint8 data
[]; // sound data
26 typedef struct sdlmixer_snd
{
33 static int devfreq
= MIX_DEFAULT_FREQUENCY
;
34 static Uint32 devformat
= AUDIO_S16SYS
; // MIX_DEFAULT_FORMAT
35 static int devchannels
= 1; // MIX_DEFAULT_CHANNELS;
36 static int devchunksize
= 1024;
37 static int devchunkchannels
= 8;
42 const cfg_t
*MUS_args (void) {
46 const cfg_t
*MUS_conf (void) {
50 const menu_t
*MUS_menu (void) {
54 void MUS_init (void) {
58 void MUS_done (void) {
62 void MUS_start (int time
) {
66 void MUS_stop (void) {
70 void MUS_volume (int v
) {
74 void MUS_load (char n
[8]) {
78 void MUS_free (void) {
82 void MUS_update (void) {
88 static int sound_menu_handler (menu_msg_t
*msg
, const menu_t
*m
, void *data
, int i
) {
90 enum { VOLUME
, __NUM__
};
91 static const simple_menu_t sm
= {
92 GM_BIG
, "Sound", NULL
,
99 case GM_GETENTRY
: return GM_init_int0(msg
, GM_SCROLLER
, 0, 0, 0);
100 case GM_GETINT
: return GM_init_int(msg
, snd_vol
, 0, 128, 8);
101 case GM_SETINT
: S_volume(msg
->integer
.i
); return 1;
104 return simple_menu_handler(msg
, i
, __NUM__
, &sm
, &cur
);
107 const menu_t
*S_menu (void) {
108 static const menu_t m
= {
109 NULL
, &sound_menu_handler
114 const cfg_t
*S_args (void) {
115 static const cfg_t args
[] = {
116 { "sndvol", &snd_vol
, Y_WORD
},
122 const cfg_t
*S_conf (void) {
123 static const cfg_t conf
[] = {
124 { "sound_volume", &snd_vol
, Y_WORD
},
131 assert(devinit
== 0);
132 logo("S_init: initialize sound\n");
133 if (SDL_InitSubSystem(SDL_INIT_AUDIO
) == 0) {
134 if (Mix_OpenAudio(devfreq
, devformat
, devchannels
, devchunksize
) == 0) {
135 Mix_AllocateChannels(devchunkchannels
);
138 logo("S_init: Mix_OpenAudio: %s\n", Mix_GetError());
139 SDL_QuitSubSystem(SDL_INIT_AUDIO
);
142 logo("S_init: SDL_InitSubSytem: %s\n", SDL_GetError());
146 static Mix_Chunk
*convert_this (int rate
, int sign
, const Uint8
*buf
, int len
) {
149 if (SDL_BuildAudioCVT(&cvt
, sign
? AUDIO_S8
: AUDIO_U8
, 1, rate
, devformat
, devchannels
, devfreq
) != -1) {
150 int maxlen
= len
* cvt
.len_mult
;
151 Uint8
*maxbuf
= malloc(maxlen
);
152 if (maxbuf
!= NULL
) {
153 memcpy(maxbuf
, buf
, len
);
156 if (SDL_ConvertAudio(&cvt
) == 0) {
157 c
= malloc(sizeof(Mix_Chunk
));
161 c
->alen
= len
* cvt
.len_ratio
;
162 c
->volume
= MIX_MAX_VOLUME
;
174 static sdlmixer_snd
*new_sdlmixer_snd (const void *data
, dword len
, dword rate
, dword lstart
, dword llen
, int sign
) {
176 sdlmixer_snd
*snd
= NULL
;
177 c
= convert_this(rate
, sign
, data
, len
);
179 snd
= malloc(sizeof(sdlmixer_snd
));
181 snd
->base
.tag
= TAG_MIX1
;
191 snd_t
*S_get (int id
) {
193 sdlmixer_snd
*snd
= NULL
;
196 if (handle
!= NULL
) {
198 dword len
= F_getreslen(id
);
205 dword hdr_len
= int2host(hdr
->len
);
206 dword hdr_rate
= int2host(hdr
->rate
);
207 dword hdr_lstart
= int2host(hdr
->lstart
);
208 dword hdr_llen
= int2host(hdr
->llen
);
209 if (hdr_len
<= len
- 8 && hdr_lstart
+ hdr_llen
<= len
- 16) {
218 snd
= new_sdlmixer_snd(data
, len
, rate
, lstart
, llen
, sign
);
225 snd_t
*S_load (const char name
[8]) {
226 int id
= F_findres(name
);
230 void S_free (snd_t
*s
) {
232 sdlmixer_snd
*snd
= (sdlmixer_snd
*)s
;
234 assert(snd
->base
.tag
== TAG_MIX1
);
236 for (i
= 0; i
< devchunkchannels
; i
++) {
237 if (Mix_GetChunk(i
) == snd
->c
) {
248 short S_play (snd_t
*s
, short c
, short v
) {
250 sdlmixer_snd
*snd
= (sdlmixer_snd
*)s
;
251 assert(c
>= 0 && c
<= 8);
252 assert(v
>= 0 && v
<= 255);
253 if (devinit
&& snd
!= NULL
) {
254 assert(snd
->base
.tag
== TAG_MIX1
);
255 // TODO care about global volume level
256 snd
->c
->volume
= v
* MIX_MAX_VOLUME
/ 255;
257 channel
= Mix_PlayChannel(c
<= 0 ? -1 : c
- 1, snd
->c
, 0);
258 channel
= channel
== -1 ? 0 : channel
+ 1;
263 void S_stop (short c
) {
264 assert(c
>= 0 && c
<= 8);
265 if (devinit
&& c
> 0) {
266 Mix_HaltChannel(c
- 1);
270 void S_volume (int v
) {
271 snd_vol
= min(max(v
, 0), 128);
273 // TODO change relativelly for every channel
274 Mix_Volume(-1, v
* MIX_MAX_VOLUME
/ 128);
280 while (Mix_Playing(-1) > 0) {
289 Mix_AllocateChannels(0);
291 SDL_QuitSubSystem(SDL_INIT_AUDIO
);