Added own channel management to SDL_mixer sound interface since the builtin channel management of this lib cannot handle our needs; Little code cleanup

This commit is contained in:
zicodxx 2011-05-30 02:17:45 +02:00
parent ea70f3db03
commit d34936d775
7 changed files with 106 additions and 89 deletions

View file

@ -1,5 +1,9 @@
D2X-Rebirth Changelog
20110530
--------
arch/include/digi_audio.h, arch/include/digi_mixer.h, arch/sdl/digi.c, arch/sdl/digi_mixer.c, main/digi.h, main/digiobj.c: Added own channel management to SDL_mixer sound interface since the builtin channel management of this lib cannot handle our needs; Little code cleanup
20110528
--------
main/net_ipx.c, main/net_udp.c: Made netgame setup menu more flexible towards (constant or temporary) changes in available game modes

View file

@ -8,7 +8,6 @@ void digi_audio_reset();
void digi_audio_close();
void digi_audio_stop_all_channels();
int digi_audio_start_sound(short, fix, int, int, int, int, int );
int digi_audio_find_channel(int );
int digi_audio_is_sound_playing(int );
int digi_audio_is_channel_playing(int );
void digi_audio_set_channel_volume(int, int );

View file

@ -10,7 +10,6 @@ void digi_mixer_set_channel_volume(int, int);
void digi_mixer_set_channel_pan(int, int);
void digi_mixer_stop_sound(int);
void digi_mixer_end_sound(int);
int digi_mixer_find_channel(int);
int digi_mixer_is_sound_playing(int);
int digi_mixer_is_channel_playing(int);
void digi_mixer_reset();

View file

@ -43,7 +43,6 @@ int (*fptr_start_sound)(short, fix, int, int, int, int, int) = NULL;
void (*fptr_stop_sound)(int) = NULL;
void (*fptr_end_sound)(int) = NULL;
int (*fptr_find_channel)(int) = NULL;
int (*fptr_is_sound_playing)(int) = NULL;
int (*fptr_is_channel_playing)(int) = NULL;
void (*fptr_stop_all_channels)() = NULL;
@ -62,7 +61,6 @@ void digi_select_system(int n) {
fptr_start_sound = digi_mixer_start_sound;
fptr_stop_sound = digi_mixer_stop_sound;
fptr_end_sound = digi_mixer_end_sound;
fptr_find_channel = digi_mixer_find_channel;
fptr_is_sound_playing = digi_mixer_is_sound_playing;
fptr_is_channel_playing = digi_mixer_is_channel_playing;
fptr_stop_all_channels = digi_mixer_stop_all_channels;
@ -80,7 +78,6 @@ void digi_select_system(int n) {
fptr_start_sound = digi_audio_start_sound;
fptr_stop_sound = digi_audio_stop_sound;
fptr_end_sound = digi_audio_end_sound;
fptr_find_channel = digi_audio_find_channel;
fptr_is_sound_playing = digi_audio_is_sound_playing;
fptr_is_channel_playing = digi_audio_is_channel_playing;
fptr_stop_all_channels = digi_audio_stop_all_channels;
@ -121,7 +118,6 @@ int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop
void digi_stop_sound(int channel) { fptr_stop_sound(channel); }
void digi_end_sound(int channel) { fptr_end_sound(channel); }
int digi_find_channel(int soundno) { return fptr_find_channel(soundno); }
int digi_is_sound_playing(int soundno) { return fptr_is_sound_playing(soundno); }
int digi_is_channel_playing(int channel) { return fptr_is_channel_playing(channel); }
void digi_stop_all_channels() { fptr_stop_all_channels(); }

View file

@ -49,134 +49,163 @@ static int digi_initialised = 0;
static int digi_max_channels = MAX_SOUND_SLOTS;
inline int fix2byte(fix f) { return (f / 256) % 256; }
Mix_Chunk SoundChunks[MAX_SOUNDS];
ubyte channels[MAX_SOUND_SLOTS];
/* Initialise audio */
int digi_mixer_init() {
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_init %d (SDL_Mixer)\n", MAX_SOUNDS);
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) Error("SDL audio initialisation failed: %s.", SDL_GetError());
int digi_mixer_init()
{
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_init %d (SDL_Mixer)\n", MAX_SOUNDS);
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) Error("SDL audio initialisation failed: %s.", SDL_GetError());
if (Mix_OpenAudio(SAMPLE_RATE_44K, MIX_OUTPUT_FORMAT, MIX_OUTPUT_CHANNELS, SOUND_BUFFER_SIZE)) {
//edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
con_printf(CON_URGENT,"\nError: Couldn't open audio: %s\n", SDL_GetError());
GameArg.SndNoSound = 1;
return 1;
}
if (Mix_OpenAudio(SAMPLE_RATE_44K, MIX_OUTPUT_FORMAT, MIX_OUTPUT_CHANNELS, SOUND_BUFFER_SIZE))
{
//edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
con_printf(CON_URGENT,"\nError: Couldn't open audio: %s\n", SDL_GetError());
GameArg.SndNoSound = 1;
return 1;
}
Mix_AllocateChannels(digi_max_channels);
Mix_Pause(0);
digi_max_channels = Mix_AllocateChannels(digi_max_channels);
memset(channels, 0, MAX_SOUND_SLOTS);
Mix_Pause(0);
digi_initialised = 1;
digi_initialised = 1;
digi_mixer_set_digi_volume( (GameCfg.DigiVolume*32768)/8 );
digi_mixer_set_digi_volume( (GameCfg.DigiVolume*32768)/8 );
return 0;
return 0;
}
/* Shut down audio */
void digi_mixer_close() {
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_close (SDL_Mixer)\n");
if (!digi_initialised) return;
digi_initialised = 0;
Mix_CloseAudio();
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_close (SDL_Mixer)\n");
if (!digi_initialised) return;
digi_initialised = 0;
Mix_CloseAudio();
}
/* channel management */
int digi_mixer_find_channel()
{
int i;
for (i = 0; i < digi_max_channels; i++)
if (channels[i] == 0)
return i;
return -1;
}
void digi_mixer_free_channel(int channel_num)
{
channels[channel_num] = 0;
}
/*
* Play-time conversion. Performs output conversion only once per sound effect used.
* Once the sound sample has been converted, it is cached in SoundChunks[]
*/
void mixdigi_convert_sound(int i) {
void mixdigi_convert_sound(int i)
{
SDL_AudioCVT cvt;
Uint8 *data = GameSounds[i].data;
Uint32 dlen = GameSounds[i].length;
int out_freq;
Uint16 out_format;
int out_channels;
SDL_AudioCVT cvt;
Uint8 *data = GameSounds[i].data;
Uint32 dlen = GameSounds[i].length;
int out_freq;
Uint16 out_format;
int out_channels;
Mix_QuerySpec(&out_freq, &out_format, &out_channels); // get current output settings
Mix_QuerySpec(&out_freq, &out_format, &out_channels); // get current output settings
if (SoundChunks[i].abuf) return; //proceed only if not converted yet
if (SoundChunks[i].abuf) return; //proceed only if not converted yet
if (data)
{
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"converting %d (%d)\n", i, dlen);
SDL_BuildAudioCVT(&cvt, AUDIO_U8, 1, GameArg.SndDigiSampleRate, out_format, out_channels, out_freq);
if (data) {
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"converting %d (%d)\n", i, dlen);
SDL_BuildAudioCVT(&cvt, AUDIO_U8, 1, GameArg.SndDigiSampleRate, out_format, out_channels, out_freq);
cvt.buf = malloc(dlen * cvt.len_mult);
cvt.len = dlen;
memcpy(cvt.buf, data, dlen);
if (SDL_ConvertAudio(&cvt)) con_printf(CON_DEBUG,"conversion of %d failed\n", i);
cvt.buf = malloc(dlen * cvt.len_mult);
cvt.len = dlen;
memcpy(cvt.buf, data, dlen);
if (SDL_ConvertAudio(&cvt)) con_printf(CON_DEBUG,"conversion of %d failed\n", i);
SoundChunks[i].abuf = cvt.buf;
SoundChunks[i].alen = dlen * cvt.len_mult;
SoundChunks[i].allocated = 1;
SoundChunks[i].volume = 128; // Max volume = 128
}
SoundChunks[i].abuf = cvt.buf;
SoundChunks[i].alen = dlen * cvt.len_mult;
SoundChunks[i].allocated = 1;
SoundChunks[i].volume = 128; // Max volume = 128
}
}
// Volume 0-F1_0
int digi_mixer_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
{
int mix_vol = fix2byte(fixmul(digi_volume, volume));
int mix_pan = fix2byte(pan);
int mix_loop = looping * -1;
int channel;
int mix_vol = fix2byte(fixmul(digi_volume, volume));
int mix_pan = fix2byte(pan);
int mix_loop = looping * -1;
int channel;
if (!digi_initialised) return -1;
Assert(GameSounds[soundnum].data != (void *)-1);
if (!digi_initialised) return -1;
Assert(GameSounds[soundnum].data != (void *)-1);
mixdigi_convert_sound(soundnum);
mixdigi_convert_sound(soundnum);
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_start_sound %d, volume %d, pan %d (start=%d, end=%d)\n", soundnum, mix_vol, mix_pan, loop_start, loop_end);
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_start_sound %d, volume %d, pan %d (start=%d, end=%d)\n", soundnum, mix_vol, mix_pan, loop_start, loop_end);
channel = digi_mixer_find_channel();
channel = Mix_PlayChannel(-1, &(SoundChunks[soundnum]), mix_loop);
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
if (volume > F1_0)
Mix_SetDistance(channel, 0);
else
Mix_SetDistance(channel, 255-mix_vol);
Mix_PlayChannel(channel, &(SoundChunks[soundnum]), mix_loop);
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
if (volume > F1_0)
Mix_SetDistance(channel, 0);
else
Mix_SetDistance(channel, 255-mix_vol);
channels[channel] = 1;
Mix_ChannelFinished(digi_mixer_free_channel);
return channel;
return channel;
}
void digi_mixer_set_channel_volume(int channel, int volume) {
int mix_vol = fix2byte(volume);
if (!digi_initialised) return;
Mix_SetDistance(channel, 255-mix_vol);
void digi_mixer_set_channel_volume(int channel, int volume)
{
int mix_vol = fix2byte(volume);
if (!digi_initialised) return;
Mix_SetDistance(channel, 255-mix_vol);
}
void digi_mixer_set_channel_pan(int channel, int pan) {
int mix_pan = fix2byte(pan);
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
void digi_mixer_set_channel_pan(int channel, int pan)
{
int mix_pan = fix2byte(pan);
Mix_SetPanning(channel, 255-mix_pan, mix_pan);
}
void digi_mixer_stop_sound(int channel) {
if (!digi_initialised) return;
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_stop_sound %d\n", channel);
Mix_HaltChannel(channel);
if (!digi_initialised) return;
if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_stop_sound %d\n", channel);
Mix_HaltChannel(channel);
channels[channel] = 0;
}
void digi_mixer_end_sound(int channel) {
digi_mixer_stop_sound(channel);
void digi_mixer_end_sound(int channel)
{
digi_mixer_stop_sound(channel);
channels[channel] = 0;
}
void digi_mixer_set_digi_volume( int dvolume )
{
digi_volume = dvolume;
if (!digi_initialised) return;
Mix_Volume(-1, fix2byte(dvolume));
digi_volume = dvolume;
if (!digi_initialised) return;
Mix_Volume(-1, fix2byte(dvolume));
}
int digi_mixer_find_channel(int soundno) { return 0; }
int digi_mixer_is_sound_playing(int soundno) { return 0; }
int digi_mixer_is_channel_playing(int channel) { return 0; }
void digi_mixer_reset() {}
void digi_mixer_stop_all_channels() {
void digi_mixer_stop_all_channels()
{
Mix_HaltChannel(-1);
memset(channels, 0, MAX_SOUND_SLOTS);
}
extern void digi_end_soundobj(int channel);
int verify_sound_channel_free(int channel);
//added on 980905 by adb to make sound channel setting work
void digi_mixer_set_max_channels(int n) { }

View file

@ -71,10 +71,6 @@ extern int digi_xlat_sound(int soundno);
extern void digi_stop_sound( int channel );
// Returns the channel a sound number is playing on, or
// -1 if none.
extern int digi_find_channel(int soundno);
// Volume 0-F1_0
extern int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj);

View file

@ -149,8 +149,6 @@ void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int l
void digi_play_sample_once( int soundno, fix max_volume )
{
int channel;
if ( Newdemo_state == ND_STATE_RECORDING )
newdemo_record_sound( soundno );
@ -158,10 +156,6 @@ void digi_play_sample_once( int soundno, fix max_volume )
if (soundno < 0 ) return;
channel=digi_find_channel(soundno);
if ( channel > -1 )
digi_stop_sound( channel );
// start the sample playing
digi_start_sound( soundno, max_volume, 0xffff/2, 0, -1, -1, -1 );
}