steed/src/steed/sound.c

313 lines
5.2 KiB
C
Raw Permalink Normal View History

2010-09-13 12:17:28 +03:00
#include "externals.h"
#include "internals.h"
2010-09-13 12:27:39 +03:00
#include <SDL.h>
#include <SDL_mixer.h>
2011-04-19 13:57:52 +03:00
#include "sdl_idf.h"
2010-09-13 12:27:39 +03:00
2011-01-11 20:41:46 +02:00
#ifdef S60
int audio_rate = 11025;
#else
2009-02-21 12:52:44 +02:00
int audio_rate = 22050;
2011-01-11 20:41:46 +02:00
#endif
2009-02-21 12:52:44 +02:00
Uint16 audio_format = MIX_DEFAULT_FORMAT;
int audio_channels = 2;
int audio_buffers = 8192;
static mus_t mus;
2009-02-21 12:52:44 +02:00
static char *next_mus = NULL;
static int next_fadein = 0;
2009-08-26 08:25:53 +03:00
static int next_loop = -1;
2011-02-19 15:23:09 +02:00
static SDL_TimerID timer_id = NULL_TIMER;
2009-02-21 12:52:44 +02:00
2009-08-26 08:25:53 +03:00
static int sound_on = 0;
struct _mus_t {
Mix_Music *mus;
SDL_RWops *rw;
};
2009-08-26 08:25:53 +03:00
static void mus_callback(void *aux)
2009-02-21 12:52:44 +02:00
{
2009-08-26 08:25:53 +03:00
if (!timer_id)
return;
if (snd_playing_mus())
return;
if (mus)
snd_free_mus(mus);
mus = NULL;
if (next_mus) {
snd_play_mus(next_mus, next_fadein, next_loop);
free(next_mus);
next_mus = NULL;
2009-02-21 12:52:44 +02:00
}
2009-08-26 08:25:53 +03:00
SDL_RemoveTimer(timer_id);
2011-02-19 15:23:09 +02:00
timer_id = NULL_TIMER;
2009-08-26 08:25:53 +03:00
}
static Uint32 callback(Uint32 interval, void *aux)
{
push_user_event(mus_callback, aux);
return interval;
2009-02-21 12:52:44 +02:00
}
int snd_hz(void)
{
int freq = 0;
2009-08-26 08:25:53 +03:00
if (sound_on)
Mix_QuerySpec(&freq, NULL, NULL);
2009-02-21 12:52:44 +02:00
return freq;
}
2009-08-26 08:25:53 +03:00
int alsa_sw = 0;
int nosound_sw = 0;
2010-03-12 17:33:10 +02:00
void snd_pause(int on)
2010-03-12 16:49:30 +02:00
{
2010-03-13 08:01:22 +02:00
if (!sound_on)
return;
2010-03-13 15:14:10 +02:00
if (on) {
Mix_Pause(-1);
2010-03-13 08:01:22 +02:00
Mix_PauseMusic();
2010-03-13 15:14:10 +02:00
} else {
Mix_Resume(-1);
2010-03-13 08:01:22 +02:00
Mix_ResumeMusic();
2010-03-13 15:14:10 +02:00
}
2010-03-12 17:33:10 +02:00
return;
2010-03-12 16:49:30 +02:00
}
2009-02-21 12:52:44 +02:00
int snd_init(int hz)
{
2011-03-30 10:28:26 +03:00
int chunk;
2009-08-26 08:25:53 +03:00
if (nosound_sw)
return -1;
2009-02-21 12:52:44 +02:00
if (!hz)
hz = audio_rate;
else
audio_rate = hz;
2009-08-26 08:25:53 +03:00
2011-03-30 10:28:26 +03:00
chunk = (chunksize_sw>0)?chunksize_sw:DEFAULT_CHUNKSIZE;
audio_buffers = (audio_rate / 11025) * chunk;
if (audio_buffers <=0) /* wrong parameter? */
audio_buffers = DEFAULT_CHUNKSIZE;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
fprintf(stderr, "Unable to init audio!\n");
return -1;
}
2009-08-26 08:25:53 +03:00
if (alsa_sw) {
SDL_AudioInit("alsa");
}
2009-02-21 12:52:44 +02:00
if (Mix_OpenAudio(hz, audio_format, audio_channels, audio_buffers)) {
fprintf(stderr, "Unable to open audio!\n");
return -1;
}
2009-08-26 08:25:53 +03:00
sound_on = 1;
2011-04-14 11:11:31 +03:00
Mix_ChannelFinished(game_channel_finished);
2009-02-21 12:52:44 +02:00
return 0;
}
int snd_volume_mus(int vol)
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return 0;
2009-02-21 12:52:44 +02:00
Mix_Volume(-1, vol);
return Mix_VolumeMusic(vol);
}
2009-08-26 08:25:53 +03:00
wav_t snd_load_wav(const char *fname)
{
2011-04-17 18:33:04 +03:00
SDL_RWops *rw;
2009-11-12 11:07:17 +02:00
wav_t r;
2009-08-26 08:25:53 +03:00
if (!sound_on)
return NULL;
2011-04-17 18:33:04 +03:00
if (!fname || !*fname)
2009-08-26 08:25:53 +03:00
return NULL;
2011-04-17 18:33:04 +03:00
rw = RWFromIdf(game_idf, fname);
if (!rw || !(r = (wav_t)Mix_LoadWAV_RW(rw, 1))) {
2009-11-12 11:07:17 +02:00
fprintf(stderr,"Can't load '%s'.\n", fname);
2011-04-17 18:33:04 +03:00
return NULL;
}
2009-11-12 11:07:17 +02:00
return r;
2009-08-26 08:25:53 +03:00
}
void snd_free_wav(wav_t w)
{
if (!w)
return;
Mix_HaltChannel(-1);
Mix_FreeChunk((Mix_Chunk*)w);
}
2009-11-12 11:07:17 +02:00
void snd_halt_chan(int han, int ms)
{
2009-11-12 11:07:17 +02:00
if (ms)
Mix_FadeOutChannel(han, ms);
else
Mix_HaltChannel(han);
}
mus_t snd_load_mus(const char *fname)
2009-02-21 12:52:44 +02:00
{
mus_t mus = NULL;
2009-08-26 08:25:53 +03:00
if (!sound_on)
return NULL;
mus = malloc(sizeof(struct _mus_t));
if (!mus)
return NULL;
2011-04-17 17:06:01 +03:00
mus->rw = RWFromIdf(game_idf, fname);
if (!mus->rw)
goto err;
mus->mus = Mix_LoadMUS_RW(mus->rw);
if (!mus->mus)
goto err1;
2009-02-21 12:52:44 +02:00
return mus;
err1:
SDL_RWclose(mus->rw);
err:
free(mus);
return NULL;
2009-02-21 12:52:44 +02:00
}
2009-08-26 08:25:53 +03:00
extern void game_music_finished(void);
2009-02-21 12:52:44 +02:00
2009-08-26 08:25:53 +03:00
int snd_play_mus(char *fname, int ms, int loop)
2009-02-21 12:52:44 +02:00
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return 0;
2009-02-21 12:52:44 +02:00
if (snd_playing_mus()) {
if (next_mus) {
free(next_mus);
}
next_mus = strdup(fname);
next_fadein = ms;
2009-08-26 08:25:53 +03:00
next_loop = loop;
2009-02-21 12:52:44 +02:00
if (!timer_id)
timer_id = SDL_AddTimer(200, callback, NULL);
return 1;
}
if (mus)
snd_free_mus(mus);
mus = snd_load_mus(fname);
2009-08-26 08:25:53 +03:00
if (!mus) {
fprintf(stderr,"Can't load '%s'.\n", fname);
2009-02-21 12:52:44 +02:00
return 0;
2009-08-26 08:25:53 +03:00
}
if (loop >= 0)
Mix_HookMusicFinished(game_music_finished);
else
Mix_HookMusicFinished(NULL);
2009-02-21 12:52:44 +02:00
if (ms)
Mix_FadeInMusic(mus->mus, loop, ms);
2009-02-21 12:52:44 +02:00
else
Mix_PlayMusic(mus->mus, loop);
2009-08-26 08:25:53 +03:00
snd_volume_mus(snd_volume_mus(-1)); // SDL hack?
2009-02-21 12:52:44 +02:00
return 0;
}
void snd_stop_mus(int ms)
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return;
Mix_HookMusicFinished(NULL);
2009-02-21 12:52:44 +02:00
if (ms)
Mix_FadeOutMusic(ms);
else
Mix_HaltMusic();
}
int snd_playing_mus(void)
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return 0;
2009-02-21 12:52:44 +02:00
if (Mix_PlayingMusic() | Mix_FadingMusic())
return 1;
return 0;
}
2009-11-12 11:07:17 +02:00
int snd_playing(int channel)
{
2010-01-04 17:25:20 +02:00
if (!sound_on)
return 0;
2009-11-12 11:07:17 +02:00
if (channel >= MIX_CHANNELS)
channel %= MIX_CHANNELS;
if (channel < 0)
channel = -1;
return Mix_Playing(channel);
}
2011-04-15 11:12:06 +03:00
int snd_panning(int channel, int left, int right)
{
if (channel >= MIX_CHANNELS)
channel %= MIX_CHANNELS;
if (channel < 0)
channel = -1;
return Mix_SetPanning(channel, left, right);
}
2009-02-21 12:52:44 +02:00
void snd_free_mus(mus_t mus)
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return;
if (!mus)
return;
2009-02-21 12:52:44 +02:00
Mix_HaltMusic();
if (mus->mus) {
#ifdef _SDL_MOD_BUG
if (Mix_GetMusicType(mus->mus) == MUS_MOD)
SDL_RWclose(mus->rw);
#endif
Mix_FreeMusic((Mix_Music*) mus->mus);
}
free(mus);
2009-02-21 12:52:44 +02:00
}
2009-11-12 18:48:54 +02:00
int snd_play(void *chunk, int channel, int loop)
2009-08-26 08:25:53 +03:00
{
if (!sound_on)
2009-11-12 18:48:54 +02:00
return -1;
2009-08-26 08:25:53 +03:00
if (!chunk)
2009-11-12 18:48:54 +02:00
return -1;
2009-11-11 21:42:12 +02:00
if (channel >= MIX_CHANNELS)
channel %= MIX_CHANNELS;
2009-11-11 22:06:18 +02:00
if (channel < 0)
2009-11-12 11:55:47 +02:00
channel = -1;
if (channel != -1)
snd_halt_chan(channel, 0);
2010-01-07 13:20:49 +02:00
snd_volume_mus(snd_volume_mus(-1)); // SDL hack?
2009-11-12 18:48:54 +02:00
return Mix_PlayChannel(channel, (Mix_Chunk*)chunk, loop);
2009-08-26 08:25:53 +03:00
}
2009-02-21 12:52:44 +02:00
void snd_done(void)
{
2009-08-26 08:25:53 +03:00
if (!sound_on)
return;
2011-04-14 11:11:31 +03:00
Mix_ChannelFinished(game_channel_finished);
if (timer_id) {
SDL_RemoveTimer(timer_id);
timer_id = NULL_TIMER;
}
2009-08-26 08:25:53 +03:00
Mix_HaltChannel(-1);
Mix_HaltMusic();
2009-02-21 12:52:44 +02:00
if (mus)
snd_free_mus(mus);
2009-02-21 12:52:44 +02:00
mus = NULL;
if (next_mus)
free(next_mus);
next_mus = NULL;
Mix_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
2009-02-21 12:52:44 +02:00
}
int snd_vol_from_pcn(int v)
{
return (v * 127) / 100;
}
int snd_vol_to_pcn(int v)
{
return (v * 100) / 127;
}