diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/aud_sdlmixer.cpp | |
| download | openparsec-main.tar.xz openparsec-main.zip | |
Diffstat (limited to 'src/parsec/aud_sdlmixer.cpp')
| -rw-r--r-- | src/parsec/aud_sdlmixer.cpp | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/src/parsec/aud_sdlmixer.cpp b/src/parsec/aud_sdlmixer.cpp new file mode 100644 index 0000000..1a36555 --- /dev/null +++ b/src/parsec/aud_sdlmixer.cpp @@ -0,0 +1,603 @@ +/* + * PARSEC - SDL Mixer Functions + * + * $Authors: mrsid $ - $Date: 2004/10/04 12:06:04 $ + * Gold-Reaver $ - $Date: 2004/10/04 12:06:04 $ + * + * Orginally written by: + * Copyright (c) Markus Hadwiger <msh@parsec.org> 1998-2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// C library +#include "config.h" +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// compilation flags/debug support +#include "config.h" +#include "debug.h" + +// general definitions +#include "general.h" +#include "objstruc.h" + +// global externals +#include "globals.h" + +// subsystem headers +#include "aud_defs.h" + +// local module header +//#include "al_null.h" +#include "snd_api.h" +#include "snd_wav.h" +#include "aud_bkgn.h" +#include "aud_supp.h" +#include "sys_file.h" +#include "sys_path.h" + +#ifdef SYSTEM_TARGET_LINUX + #include <SDL/SDL.h> + #include <SDL/SDL_mixer.h> +#else + #include <SDL.h> + #include <SDL_mixer.h> +#endif +// flags + +static int snd_init_done = FALSE; +static int in_game_mode = FALSE; +Mix_Chunk *snd_chunks[MAX_SAMPLES]; +Mix_Music *music; +char *tmp_music_buffer = NULL; + +// play the specified sound on channel voice ---------------------------------- +// +int AUDs_PlayVoice( int voice, int sound ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_PlayChannel(voice, snd_chunks[sound], 0); + + return AUD_RETURN_SUCCESS; +} + + +// play the specified wave on channel voice with normal stereo ---------------- +// +int AUDs_PlayVoiceBuffer( int voice, audiowave_t wave, SoundParams_s *params ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + if (params != NULL) { + + if ( !(params->flags & SOUNDPARAMS_LOOP) ) { + params->numLoops = 0; + } else { + if( !(params->flags & SOUNDPARAMS_LOOP_COUNT)) + params->numLoops = -1; + } + + Mix_PlayChannel(voice, snd_chunks[(long)wave], params->numLoops ); + + } else { + + Mix_PlayChannel(voice, snd_chunks[(long)wave], 0); + return AUD_RETURN_SUCCESS; + + } + + + if ( params->flags & SOUNDPARAMS_VOLUME) { + if (params->volume > 128) + params->volume = 128; + + Mix_Volume(voice, params->volume); + } + + return AUD_RETURN_SUCCESS; +} + + +// set the volume for the specified channel ----------------------------------- +// +int AUDs_SetVoiceVolume( int voice, int volume ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + if (volume > 128) + volume = 128; + + Mix_Volume(voice, volume); + + return AUD_RETURN_SUCCESS; +} + + +// load wave file into memory ------------------------------------------------- +// +PUBLIC int aud_sample_quality = 44100; + +int AUDs_LoadWaveFile( int num ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + ASSERT( ( num >= 0 ) && ( num < MAX_SAMPLES ) ); + + if ( !SoundAvailable ) + return AUD_RETURN_SUCCESS; + + // read the sample and assign the list entry + sample_s* pSample = SND_ReadSample( &SampleInfo[ num ] ); + + SND_ConvertRate( pSample, aud_sample_quality ); + + // numframes are number of individual samples + dword numframes = pSample->samplebytes / pSample->alignment; + + // because SDL_RWFromFP doesn't work cross platform, we need + // to get a little bit kinky + + // set up a buffer for the file + char *tmp_sample_buffer = NULL; + size_t tmp_sample_size = 0; + + // get the size of this sample + tmp_sample_size = SYS_GetFileLength(SampleInfo[num].file); + if (tmp_sample_size <= 0) { + return FALSE; // return on error + } + + // alloc space for the buffer + tmp_sample_buffer = (char *)ALLOCMEM(tmp_sample_size + 1); + + // open the sample file + FILE *wave = SYS_fopen(SampleInfo[num].file, "rb"); + + if (wave == NULL) + return FALSE; + + // read the file into the temp_sample_buffer + int read_rc = SYS_fread((void *)tmp_sample_buffer, 1, tmp_sample_size, wave); + + if (read_rc <= 0) { + MSGOUT("ERROR: Error reading sample %s.", SampleInfo[num].file); + return FALSE; + } + + SDL_RWops *waverwops = SDL_RWFromMem((void *)tmp_sample_buffer, tmp_sample_size); + snd_chunks[num] = Mix_LoadWAV_RW(waverwops, 1); + SYS_fclose(wave); + + FREEMEM( tmp_sample_buffer ); + FREEMEM( pSample->samplebuffer ); + pSample->samplebuffer = NULL; + + +#ifdef SHOW_SAMPLE_LOADING_INFO + + MSGOUT("loaded %-12s to slot %03d: rate: %05d, numch: %02d, type: %s, bytes: %07d", + SampleInfo[ num ].file, num, pSample->samplerate, pSample->numchannels, + ( pSample->samplesize == 8 ) ? "8" : "16" , pSample->samplebytes ); + +#endif // SHOW_SAMPLE_LOADING_INFO + + // store the slot submitted to the play functions + SampleInfo[ num ].samplepointer = (char *)num; + + //CAVEAT: for now we store the number of refframes in size + SampleInfo[ num ].size = FLOAT2INT( (float) FRAME_MEASURE_TIMEBASE * + (float) pSample->samplebytes / (float) ( pSample->samplerate * pSample->alignment ) + 0.5f ); + + FREEMEM( pSample ); + + return AUD_RETURN_SUCCESS; +} + + +// free resources associated with wave file ----------------------------------- +// +int AUDs_FreeWaveFile( int num ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + ASSERT( ( num >= 0 ) && ( num < MAX_SAMPLES ) ); + + if ( !SoundAvailable ) + return AUD_RETURN_SUCCESS; + + Mix_FreeChunk(snd_chunks[num]); + + return AUD_RETURN_SUCCESS; +} + + +// set panning of channel voice ----------------------------------------------- +// +int AUDs_SetVoicePanning( int voice, int panning ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_SetPanning(voice, panning, panning); + + return AUD_RETURN_SUCCESS; +} + + +// set frequency of channel voice --------------------------------------------- +// +int AUDs_SetVoiceFrequency( int voice, int freq ) +{ + return AUD_RETURN_SUCCESS; +} + + +// get replay status of channel voice ----------------------------------------- +// +int AUDs_GetVoiceStatus( int voice, int *stopped ) +{ + ASSERT( stopped != NULL ); + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + *stopped = !Mix_Playing(voice); + return AUD_RETURN_SUCCESS; +} + + +// stop replay on channel voice ----------------------------------------------- +// +int AUDs_StopVoice( int voice, int finishloop ) +{ + if (SoundDisabled) + return AUD_RETURN_SUCCESS; + + Mix_HaltChannel(voice); + return AUD_RETURN_SUCCESS; +} + + +// speak text string ---------------------------------------------------------- +// +int AUDs_SpeakString( char *speakstr ) +{ + return 0; +} + + +// init sound stuff for game mode --------------------------------------------- +// +int AUDs_OpenGameSound() +{ + + return 1; +} + + +// kill sound stuff for game mode --------------------------------------------- +// +int AUDs_CloseGameSound() +{ + return 1; +} + + +// play specified stream file ------------------------------------------------- +// +int AUDs_PlayAudioStream( char *fname ) +{ + + if (SoundDisabled) + return 1; + + ASSERT(fname!=NULL); + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + music = NULL; + } + // because SDL_RWFromFP doesn't work cross platform, we need + // to get a little bit kinky + + // set up a buffer for the file + + size_t tmp_music_size = 0; + + // get the size of this sample + tmp_music_size = SYS_GetFileLength(fname); + if (tmp_music_size <= 0) { + return 1; // return on error + } + + // alloc space for the buffer + if (tmp_music_buffer != NULL) { + printf("ERROR: Shouldn't be this far without being cleaned up previously\n"); + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + tmp_music_buffer = (char *)ALLOCMEM(tmp_music_size + 1); + + // open the sample file + FILE *musicfp = SYS_fopen(fname, "rb"); + if (musicfp == NULL) + return 1; + + // read the file into the temp_sample_buffer + int read_rc = SYS_fread((void *)tmp_music_buffer, 1, tmp_music_size, musicfp); + + if(read_rc <= 0) { + MSGOUT("ERROR: Error reading music %s.", fname); + return FALSE; + } + + SDL_RWops * musicrwops = SDL_RWFromMem((void *)tmp_music_buffer, tmp_music_size); + + music = Mix_LoadMUS_RW(musicrwops); + //MSGOUT(" PlayAudioStream() with %s ", fname); + if (music == NULL) { + printf("Mix_LoadMUS(\"%s\"): %s\n", fname, Mix_GetError()); + // this might be a critical error... + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + return 1; + } + + Mix_VolumeMusic(128); + + if (music != NULL) { + Mix_PlayMusic(music, 0); + } + + //Pick up your your toys when you finish + SYS_fclose(musicfp); + + return 1; +} + + +// stop replay of stream file ------------------------------------------------- +// +int AUDs_StopAudioStream() +{ +// Mix_HaltChannel(1); + if (SoundDisabled) + return 1; + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + music = NULL; + } + + if (tmp_music_buffer != NULL) { + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + return 1; +} + + +// precache sound effects specified in control file --------------------------- +// +void AUDs_LoadAllSoundEffects() +{ + if (SoundDisabled) + return; + + for (int i = 0; i < NumLoadedSamples; i++) + AUDs_LoadWaveFile(i); +} + + +// free sound effects that have been precached -------------------------------- +// +void AUDs_FreeAllSoundEffects() +{ + if (SoundDisabled) + return; + + for (int sid = 0; sid < NumLoadedSamples; sid++) { + AUDs_FreeWaveFile( sid ); + } +} + + +// init sound stuff for game menu --------------------------------------------- +// +int AUDs_OpenMenuSound() +{ + if (SoundDisabled) + return 1; + + in_game_mode = FALSE; + + if (Mix_PlayingMusic()) + Mix_HaltMusic(); + + AUDs_PlayAudioStream( menu_stream_name ); + + return 1; +} + + +// kill sound stuff for game menu --------------------------------------------- +// +int AUDs_CloseMenuSound() +{ + if (SoundDisabled) + return 1; + + AUDs_StopAudioStream(); + + return 1; +} + + +// init sound stuff for intro animation --------------------------------------- +// +int AUDs_OpenIntroSound() +{ + return 1; +} + + +// kill sound stuff for intro animation --------------------------------------- +// +int AUDs_CloseIntroSound() +{ + return 1; +} + + +// init sound stuff for credits scroller -------------------------------------- +// +int AUDs_OpenCreditsSound() +{ + return 1; +} + + +// kill sound stuff for credits scroller -------------------------------------- +// +int AUDs_CloseCreditsSound() +{ + return 1; +} + + +// set music/stream volume to maximum ----------------------------------------- +// +void AUDs_MaxMusicVolume() +{ + Mix_VolumeMusic(MIX_MAX_VOLUME); +} + + +// set music/stream volume to zero -------------------------------------------- +// +void AUDs_MinMusicVolume() +{ + Mix_VolumeMusic(0); +} + + +// decrease music/stream volume (no continuous fading!) ----------------------- +// +void AUDs_FadeMusicVolume() +{ +} + + +// maintain sound by keeping the output buffer filled ------------------------- +// +void AUDs_MaintainSound() +{ + if ( SoundDisabled ) + return; + + if (!Mix_PlayingMusic() && in_game_mode == FALSE) { + AUD_BackGroundPlayer_Start(FALSE); + in_game_mode = TRUE; + } + + if (!Mix_PlayingMusic()) + AUD_BackGroundPlayer_Start(FALSE); +} + +void AUDs_MusicFinished() +{ + if (in_game_mode) { + // just in case, not that it would matter. + Mix_HaltMusic(); + + if (music != NULL) { + Mix_FreeMusic(music); + music = NULL; + } + + if (tmp_music_buffer != NULL) { + FREEMEM(tmp_music_buffer); + tmp_music_buffer = NULL; + } + + // signal the BackGround Player we're ready for the next song. + AUD_BackGroundPlayer_Start(FALSE); + } +} + +// init sound system and sound hardware --------------------------------------- +// +int AUDs_InitSoundSys() +{ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + MSGOUT("Failed to open audio.\n"); + SoundDisabled = TRUE; + return FALSE; + } + + if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096) == -1) { + MSGOUT("Could not open mixer.\n%s\n",Mix_GetError()); + SoundDisabled = TRUE; + return FALSE; + } + + Mix_AllocateChannels(32); + Mix_Volume(-1, MIX_MAX_VOLUME); + + AUDs_LoadAllSoundEffects(); + AUD_BackGroundPlayer_Init(1); + + //Mix_HookMusicFinished(AUDs_MusicFinished); + + MSGOUT("Sound Init Done\n"); + + snd_init_done = TRUE; + return TRUE; +} + + +// cancel sound system and sound hardware ------------------------------------- +// +int AUDs_KillSoundSys() +{ + AUDs_FreeAllSoundEffects(); + AUD_BackGroundPlayer_Kill(); + + Mix_CloseAudio(); + SDL_Quit(); + + return TRUE; +} + + |
