00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "s_local.h"
00027 #include "s_main.h"
00028 #include "s_music.h"
00029 #include "s_sample.h"
00030 #include "s_mix.h"
00031
00032 #define COMPARE_VERSION(major,minor,micro) \
00033 (SDL_MIXER_MAJOR_VERSION > (major) || \
00034 (SDL_MIXER_MAJOR_VERSION == (major) && SDL_MIXER_MINOR_VERSION > (minor)) || \
00035 (SDL_MIXER_MAJOR_VERSION == (major) && SDL_MIXER_MINOR_VERSION == (minor) && \
00036 SDL_MIXER_PATCHLEVEL >= (micro)))
00037
00038 s_env_t s_env;
00039
00040 cvar_t *snd_volume;
00041 cvar_t *snd_distance_scale;
00042 static cvar_t *snd_init;
00043 static cvar_t *snd_rate;
00044
00045 static void S_Restart_f(void);
00046
00050 void S_Stop (void)
00051 {
00052 if (!s_env.initialized)
00053 return;
00054 Mix_HaltChannel(-1);
00055
00056 memset(s_env.channels, 0, sizeof(s_env.channels));
00057 }
00058
00062 void S_Frame (void)
00063 {
00064 if (snd_init && snd_init->modified) {
00065 S_Restart_f();
00066 snd_init->modified = qfalse;
00067 }
00068
00069 if (!s_env.initialized)
00070 return;
00071
00072 M_Frame();
00073
00074 if (CL_OnBattlescape()) {
00075 int i;
00076 s_channel_t *ch;
00077 le_t *le;
00078
00079
00080 AngleVectors(cl.cam.angles, NULL, s_env.right, NULL);
00081
00082
00083 ch = s_env.channels;
00084
00085 for (i = 0; i < MAX_CHANNELS; i++, ch++) {
00086 if (!ch->sample)
00087 continue;
00088
00089
00090 ch->count = 0;
00091
00092 S_SpatializeChannel(ch);
00093 }
00094
00095
00096 le = NULL;
00097 while ((le = LE_GetNextInUse(le))) {
00098 if (le->type == ET_SOUND) {
00099 int j;
00100 for (j = 0; j < MAX_CHANNELS; j++) {
00101 if (s_env.channels[j].sample == le->sample)
00102 break;
00103 }
00104
00105 if (j == MAX_CHANNELS)
00106 S_LoopSample(le->origin, le->sample, le->volume, le->attenuation);
00107 }
00108 }
00109 }
00110 }
00111
00115 static void S_Play_f (void)
00116 {
00117 int i;
00118
00119 if (Cmd_Argc() < 2) {
00120 Com_Printf("Usage: %s <filename> [<filename> ...]\n", Cmd_Argv(0));
00121 return;
00122 }
00123
00124 i = 1;
00125 while (i < Cmd_Argc()) {
00126 S_StartLocalSample(Cmd_Argv(i), SND_VOLUME_DEFAULT);
00127 i++;
00128 }
00129 }
00130
00136 static void S_Restart_f (void)
00137 {
00138 Com_Printf("Restarting sound\n");
00139 S_Shutdown();
00140 S_Init();
00141 S_LoadSamples();
00142 }
00143
00144 static int S_CompleteSounds (const char *partial, const char **match)
00145 {
00146 const char *filename;
00147 int matches = 0;
00148 char *localMatch[MAX_COMPLETE];
00149 size_t len = strlen(partial);
00150 const char *soundExtensions[] = SAMPLE_TYPES;
00151 const char **extension = soundExtensions;
00152 int returnValue;
00153
00154
00155 while (*extension) {
00156 char pattern[MAX_OSPATH];
00157 Com_sprintf(pattern, sizeof(pattern), "sound/**.%s", *extension);
00158 FS_BuildFileList(pattern);
00159 while ((filename = FS_NextFileFromFileList(pattern)) != NULL) {
00160 char fileWithPath[MAX_OSPATH];
00161 Com_sprintf(fileWithPath, sizeof(fileWithPath), "%s", filename + 6);
00162 if (!len) {
00163 Com_Printf("%s\n", fileWithPath);
00164 } else if (!strncmp(partial, fileWithPath, len)) {
00165 Com_Printf("%s\n", fileWithPath);
00166 localMatch[matches++] = strdup(fileWithPath);
00167 if (matches >= MAX_COMPLETE)
00168 break;
00169 }
00170 }
00171 FS_NextFileFromFileList(NULL);
00172 extension++;
00173 }
00174
00175 returnValue = Cmd_GenericCompleteFunction(len, match, matches, (const char **)localMatch);
00176 while (--matches >= 0)
00177 free(localMatch[matches]);
00178 return returnValue;
00179 }
00180
00185 void S_Init (void)
00186 {
00187 SDL_version version;
00188 char drivername[MAX_VAR];
00189
00190 Com_Printf("\n------- sound initialization -------\n");
00191
00192 memset(&s_env, 0, sizeof(s_env));
00193
00194 snd_init = Cvar_Get("snd_init", "1", CVAR_ARCHIVE, "Should the sound renderer get initialized");
00195 snd_init->modified = qfalse;
00196 Cmd_AddCommand("snd_restart", S_Restart_f, "Restart the sound renderer");
00197
00198 if (!snd_init->integer) {
00199 Com_Printf("not initializing.\n");
00200 Cmd_AddCommand("music_change", Cmd_Dummy_f, "Dummy command if sound is disabled");
00201 Cvar_Get("snd_music", "PsymongN3", 0, "Background music track");
00202 return;
00203 }
00204
00205 snd_distance_scale = Cvar_Get("snd_distance_scale", "0.1", 0, "Sound distance scale");
00206 snd_volume = Cvar_Get("snd_volume", "0.7", CVAR_ARCHIVE, "Sound volume - default is 0.7");
00207 snd_rate = Cvar_Get("snd_rate", "44100", CVAR_ARCHIVE, "Hz value for sound renderer - default is 44100");
00208
00210 snd_volume->modified = qtrue;
00211
00212 Cmd_AddCommand("snd_play", S_Play_f, "Plays a sound fx file. Pass path relative to base/sound without file extension");
00213 Cmd_AddParamCompleteFunction("snd_play", S_CompleteSounds);
00214
00215 if (SDL_WasInit(SDL_INIT_AUDIO) == 0) {
00216 if (SDL_Init(SDL_INIT_AUDIO) < 0) {
00217 Com_Printf("S_Init: %s.\n", SDL_GetError());
00218 return;
00219 }
00220 }
00221
00222 MIX_VERSION(&version)
00223 Com_Printf("SDL_mixer version: %d.%d.%d\n", version.major, version.minor, version.patch);
00224 Com_Printf("... requested audio rate: %i\n", snd_rate->integer);
00225
00226 if (Mix_OpenAudio(snd_rate->integer, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) == -1) {
00227 Com_Printf("S_Init: %s\n", Mix_GetError());
00228 return;
00229 }
00230
00231 if (Mix_QuerySpec(&s_env.rate, &s_env.format, &s_env.numChannels) == 0) {
00232 Com_Printf("S_Init: %s\n", Mix_GetError());
00233 return;
00234 }
00235
00236 if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
00237 Q_strncpyz(drivername, "(UNKNOWN)", sizeof(drivername));
00238 Com_Printf("... driver: '%s'\n", drivername);
00239
00240 if (Mix_AllocateChannels(MAX_CHANNELS) != MAX_CHANNELS) {
00241 Com_Printf("S_Init: %s\n", Mix_GetError());
00242 return;
00243 }
00244
00245 Mix_ChannelFinished(S_FreeChannel);
00246
00247 Com_Printf("... audio rate: %i\n", s_env.rate);
00248 Com_Printf("... audio channels: %i\n", s_env.numChannels);
00249
00250 #if COMPARE_VERSION(1, 2, 10)
00251 if (!(Mix_Init(MIX_INIT_OGG) & MIX_INIT_OGG))
00252 Com_Printf("... could not load ogg vorbis support\n");
00253 else
00254 Com_Printf("... loaded ogg vorbis support\n");
00255 #endif
00256
00257 s_env.initialized = qtrue;
00258
00259 M_Init();
00260 }
00261
00266 void S_Shutdown (void)
00267 {
00268 if (!s_env.initialized)
00269 return;
00270
00271 M_Shutdown();
00272
00273 S_Stop();
00274
00275 Mix_AllocateChannels(0);
00276
00277 S_FreeSamples();
00278
00279 Mix_CloseAudio();
00280
00281 if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_AUDIO)
00282 SDL_Quit();
00283 else
00284 SDL_QuitSubSystem(SDL_INIT_AUDIO);
00285
00286 Mem_FreeTag(cl_soundSysPool, 0);
00287
00288 Cmd_RemoveCommand("snd_play");
00289 Cmd_RemoveCommand("snd_restart");
00290
00291 #if COMPARE_VERSION(1, 2, 10)
00292 Mix_Quit();
00293 #endif
00294
00295 s_env.initialized = qfalse;
00296 }