638ec34d3e5ffd0929b197622ba334f3bb32ec0b
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
= { sound_menu_handler
};
112 const cfg_t
*S_args (void) {
113 static const cfg_t args
[] = {
114 { "sndvol", &snd_vol
, Y_WORD
},
120 const cfg_t
*S_conf (void) {
121 static const cfg_t conf
[] = {
122 { "sound_volume", &snd_vol
, Y_WORD
},
129 assert(devinit
== 0);
130 logo("S_init: initialize sound\n");
131 if (SDL_InitSubSystem(SDL_INIT_AUDIO
) == 0) {
132 if (Mix_OpenAudio(devfreq
, devformat
, devchannels
, devchunksize
) == 0) {
133 Mix_AllocateChannels(devchunkchannels
);
136 logo("S_init: Mix_OpenAudio: %s\n", Mix_GetError());
137 SDL_QuitSubSystem(SDL_INIT_AUDIO
);
140 logo("S_init: SDL_InitSubSytem: %s\n", SDL_GetError());
144 static Mix_Chunk
*convert_this (int rate
, int sign
, const Uint8
*buf
, int len
) {
147 if (SDL_BuildAudioCVT(&cvt
, sign
? AUDIO_S8
: AUDIO_U8
, 1, rate
, devformat
, devchannels
, devfreq
) != -1) {
148 int maxlen
= len
* cvt
.len_mult
;
149 Uint8
*maxbuf
= malloc(maxlen
);
150 if (maxbuf
!= NULL
) {
151 memcpy(maxbuf
, buf
, len
);
154 if (SDL_ConvertAudio(&cvt
) == 0) {
155 c
= malloc(sizeof(Mix_Chunk
));
159 c
->alen
= len
* cvt
.len_ratio
;
160 c
->volume
= MIX_MAX_VOLUME
;
172 static sdlmixer_snd
*new_sdlmixer_snd (const void *data
, dword len
, dword rate
, dword lstart
, dword llen
, int sign
) {
174 sdlmixer_snd
*snd
= NULL
;
175 c
= convert_this(rate
, sign
, data
, len
);
177 snd
= malloc(sizeof(sdlmixer_snd
));
179 snd
->base
.tag
= TAG_MIX1
;
189 snd_t
*S_get (int id
) {
191 sdlmixer_snd
*snd
= NULL
;
194 if (handle
!= NULL
) {
196 dword len
= F_getreslen(id
);
203 dword hdr_len
= int2host(hdr
->len
);
204 dword hdr_rate
= int2host(hdr
->rate
);
205 dword hdr_lstart
= int2host(hdr
->lstart
);
206 dword hdr_llen
= int2host(hdr
->llen
);
207 if (hdr_len
<= len
- 8 && hdr_lstart
+ hdr_llen
<= len
- 16) {
216 snd
= new_sdlmixer_snd(data
, len
, rate
, lstart
, llen
, sign
);
223 snd_t
*S_load (const char name
[8]) {
224 int id
= F_findres(name
);
228 void S_free (snd_t
*s
) {
230 sdlmixer_snd
*snd
= (sdlmixer_snd
*)s
;
232 assert(snd
->base
.tag
== TAG_MIX1
);
234 for (i
= 0; i
< devchunkchannels
; i
++) {
235 if (Mix_GetChunk(i
) == snd
->c
) {
246 short S_play (snd_t
*s
, short c
, short v
) {
248 sdlmixer_snd
*snd
= (sdlmixer_snd
*)s
;
249 assert(c
>= 0 && c
<= 8);
250 assert(v
>= 0 && v
<= 255);
251 if (devinit
&& snd
!= NULL
) {
252 assert(snd
->base
.tag
== TAG_MIX1
);
253 // TODO care about global volume level
254 snd
->c
->volume
= v
* MIX_MAX_VOLUME
/ 255;
255 channel
= Mix_PlayChannel(c
<= 0 ? -1 : c
- 1, snd
->c
, 0);
256 channel
= channel
== -1 ? 0 : channel
+ 1;
261 void S_stop (short c
) {
262 assert(c
>= 0 && c
<= 8);
263 if (devinit
&& c
> 0) {
264 Mix_HaltChannel(c
- 1);
268 void S_volume (int v
) {
269 snd_vol
= min(max(v
, 0), 128);
271 // TODO change relativelly for every channel
272 Mix_Volume(-1, v
* MIX_MAX_VOLUME
/ 128);
278 while (Mix_Playing(-1) > 0) {
287 Mix_AllocateChannels(0);
289 SDL_QuitSubSystem(SDL_INIT_AUDIO
);