s_mix.c
Go to the documentation of this file.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_mix.h"
00028 #include "s_main.h"
00029
00034 static int S_AllocChannel (void)
00035 {
00036 int i;
00037
00038 for (i = 0; i < MAX_CHANNELS; i++) {
00039 if (!s_env.channels[i].sample)
00040 return i;
00041 }
00042
00043 return -1;
00044 }
00045
00050 void S_FreeChannel (int c)
00051 {
00052 memset(&s_env.channels[c], 0, sizeof(s_env.channels[0]));
00053 }
00054
00059 void S_SpatializeChannel (const s_channel_t *ch)
00060 {
00061 vec3_t delta;
00062 float dist, angle;
00063 const int c = (int)((ptrdiff_t)(ch - s_env.channels));
00064
00065 VectorSubtract(ch->org, cl.cam.camorg, delta);
00066
00067 dist = VectorNormalize(delta) * snd_distance_scale->value * ch->atten;
00068
00069 if (dist > 255.0)
00070 dist = 255.0;
00071
00072 if (dist > 50.0) {
00073 const float dot = DotProduct(s_env.right, delta);
00074 angle = (int)(450.0 - acos(dot) * todeg) % 360;
00075 } else
00076 angle = 0;
00077
00078 Mix_SetPosition(c, (int)angle, (int)dist);
00079 }
00080
00091 void S_PlaySample (const vec3_t origin, s_sample_t* sample, float atten, float relVolume)
00092 {
00093 s_channel_t *ch;
00094 int i;
00095 float volume;
00096
00097 if (!s_env.initialized)
00098 return;
00099
00100 if (!sample)
00101 return;
00102
00103
00104 if (sample->lastPlayed > CL_Milliseconds() - s_env.sampleRepeatRate)
00105 return;
00106
00107 if ((i = S_AllocChannel()) == -1)
00108 return;
00109
00110 sample->lastPlayed = CL_Milliseconds();
00111 ch = &s_env.channels[i];
00112
00113 ch->atten = atten;
00114 ch->sample = sample;
00115
00116 if (origin != NULL) {
00117 VectorCopy(origin, ch->org);
00118 S_SpatializeChannel(ch);
00119 }
00120
00121 volume = snd_volume->value * relVolume * MIX_MAX_VOLUME;
00122 Com_DPrintf(DEBUG_SOUND, "%i: Playing sample '%s' at volume %f at channel %i\n",
00123 CL_Milliseconds(), sample->name, volume, i);
00124 Mix_VolumeChunk(ch->sample->chunk, volume);
00125 Mix_PlayChannel(i, ch->sample->chunk, 0);
00126 }
00127
00131 void S_LoopSample (const vec3_t org, s_sample_t *sample, float volume, float attenuation)
00132 {
00133 s_channel_t *ch;
00134 int i;
00135
00136 if (!sample || !sample->chunk)
00137 return;
00138
00139 ch = NULL;
00140
00141 for (i = 0; i < MAX_CHANNELS; i++){
00142 if (s_env.channels[i].sample == sample) {
00143 vec3_t delta;
00144 VectorSubtract(s_env.channels[i].org, org, delta);
00145 if (VectorLength(delta) < 255.0) {
00146 ch = &s_env.channels[i];
00147 break;
00148 }
00149 }
00150 }
00151
00152 if (ch) {
00153 ch->count++;
00154
00155 VectorMix(ch->org, org, 1.0 / ch->count, ch->org);
00156 } else {
00157 if ((i = S_AllocChannel()) == -1)
00158 return;
00159
00160 ch = &s_env.channels[i];
00161
00162 sample->lastPlayed = CL_Milliseconds();
00163 VectorCopy(org, ch->org);
00164 ch->count = 1;
00165 ch->atten = attenuation;
00166 ch->sample = sample;
00167
00168 Mix_PlayChannel(i, ch->sample->chunk, 0);
00169 }
00170
00171 S_SpatializeChannel(ch);
00172 }
00173
00181 void S_StartLocalSample (const char *name, float relVolume)
00182 {
00183 s_sample_t *sample;
00184
00185 if (!s_env.initialized)
00186 return;
00187
00188 sample = S_LoadSample(name);
00189 if (!sample) {
00190 Com_Printf("S_StartLocalSample: Failed to load %s\n", name);
00191 return;
00192 }
00193 S_PlaySample(NULL, sample, SOUND_ATTN_NORM, relVolume);
00194 }