UFO: Alien Invasion
Loading...
Searching...
No Matches
s_mix.cpp
Go to the documentation of this file.
1
5
6/*
7All original material Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "../cl_shared.h"
27#include "../cl_renderer.h"
28#include "../cl_video.h"
32
33#include "s_mix.h"
34#include "s_sample.h"
35#include "s_main.h"
36
41static int S_AllocChannel (void)
42{
43 for (int i = 0; i < MAX_CHANNELS; i++) {
44 if (!s_env.channels[i].sample)
45 return i;
46 }
47
48 return -1;
49}
50
55void S_FreeChannel (int c)
56{
57 OBJZERO(s_env.channels[c]);
58}
59
65{
66 vec3_t delta;
67 float angle;
68 const int c = (int)((ptrdiff_t)(ch - s_env.channels));
69
70 VectorSubtract(ch->org, cl.cam.camorg, delta);
71
72 float dist = VectorNormalize(delta) * snd_distance_scale->value * ch->atten;
73
74 if (dist > 255.0) /* clamp to max */
75 dist = 255.0;
76
77 if (dist > 50.0) { /* resolve stereo panning */
78 const float dot = DotProduct(s_env.right, delta);
79 angle = (int)(450.0 - acos(dot) * todeg) % 360;
80 } else
81 angle = 0;
82
83 Mix_SetPosition(c, (int)angle, (int)dist);
84}
85
96void S_PlaySample (const vec3_t origin, s_sample_t* sample, float atten, float relVolume)
97{
98
99 if (!s_env.initialized)
100 return;
101
102 if (!sample)
103 return;
104
105 /* if the last mix of this particular sample is less than half a second ago, skip it */
106 if (sample->lastPlayed > CL_Milliseconds() - s_env.sampleRepeatRate)
107 return;
108
109 const int chIdx = S_AllocChannel();
110 if (chIdx == -1)
111 return;
112
113 sample->lastPlayed = CL_Milliseconds();
114 s_channel_t* ch = &s_env.channels[chIdx];
115
116 ch->atten = atten;
117 ch->sample = sample;
118
119 if (origin != nullptr) {
120 VectorCopy(origin, ch->org);
122 }
123
124 const float volume = snd_volume->value * relVolume * MIX_MAX_VOLUME;
125 Com_DPrintf(DEBUG_SOUND, "%i: Playing sample '%s' at volume %f at channel %i\n",
126 CL_Milliseconds(), sample->name, volume, chIdx);
127 Mix_VolumeChunk(ch->sample->chunk, volume);
128 Mix_PlayChannel(chIdx, ch->sample->chunk, 0);
129}
130
134void S_LoopSample (const vec3_t org, s_sample_t* sample, float relVolume, float attenuation)
135{
136 if (!sample || !sample->chunk)
137 return;
138
139 s_channel_t* ch = nullptr;
140
141 for (int i = 0; i < MAX_CHANNELS; i++){ /* find existing loop sound */
142 if (s_env.channels[i].sample == sample) {
143 vec3_t delta;
144 VectorSubtract(s_env.channels[i].org, org, delta);
145 if (VectorLength(delta) < 255.0) {
146 ch = &s_env.channels[i];
147 break;
148 }
149 }
150 }
151
152 if (ch) { /* update existing loop sample */
153 ch->count++;
154
155 VectorMix(ch->org, org, 1.0 / ch->count, ch->org);
156 } else { /* or allocate a new one */
157 const int chIdx = S_AllocChannel();
158 if (chIdx == -1)
159 return;
160
161 ch = &s_env.channels[chIdx];
162
163 sample->lastPlayed = CL_Milliseconds();
164 VectorCopy(org, ch->org);
165 ch->count = 1;
166 ch->atten = attenuation;
167 ch->sample = sample;
168
169 float volume = snd_volume->value * relVolume * MIX_MAX_VOLUME;
170 Mix_VolumeChunk(ch->sample->chunk, volume);
171 Mix_PlayChannel(chIdx, ch->sample->chunk, 0);
172 }
173
175}
176
184void S_StartLocalSample (const char* name, float relVolume)
185{
186 if (!s_env.initialized)
187 return;
188
189 s_sample_t* sample = S_LoadSample(name);
190 if (!sample) {
191 Com_Printf("S_StartLocalSample: Failed to load %s\n", name);
192 return;
193 }
194 S_PlaySample(nullptr, sample, SOUND_ATTN_NORM, relVolume);
195}
clientBattleScape_t cl
int CL_Milliseconds(void)
Definition cl_main.cpp:1207
Share stuff between the different cgame implementations.
Video driver defs.
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define SOUND_ATTN_NORM
Definition common.h:186
#define DEBUG_SOUND
Definition defines.h:63
voidpf uLong int origin
Definition ioapi.h:45
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition mathlib.cpp:745
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition mathlib.cpp:434
void VectorMix(const vec3_t v1, const vec3_t v2, float mix, vec3_t out)
Calculate a position on v1 v2 line.
Definition mathlib.cpp:447
#define todeg
Definition mathlib.h:51
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
cvar_t * snd_volume
Definition s_main.cpp:42
#define MAX_CHANNELS
the sound environment
Definition s_local.h:58
cvar_t * snd_distance_scale
Definition s_main.cpp:43
s_env_t s_env
Definition s_main.cpp:40
s_sample_t * S_LoadSample(const char *soundFile)
Loads and registers a sound file for later use.
Definition s_main.cpp:335
Specifies sound API?
void S_FreeChannel(int c)
Callback that is called when a channel finished playing.
Definition s_mix.cpp:55
void S_LoopSample(const vec3_t org, s_sample_t *sample, float relVolume, float attenuation)
Adds a loop sample for e.g. ambient sounds.
Definition s_mix.cpp:134
void S_StartLocalSample(const char *name, float relVolume)
Plays a sample without spatialization.
Definition s_mix.cpp:184
static int S_AllocChannel(void)
Searches a channel with no sample applied yet.
Definition s_mix.cpp:41
void S_PlaySample(const vec3_t origin, s_sample_t *sample, float atten, float relVolume)
Validates the parms and queues the sound up.
Definition s_mix.cpp:96
void S_SpatializeChannel(const s_channel_t *ch)
Set distance and stereo panning for the specified channel.
Definition s_mix.cpp:64
Specifies sound API?
#define OBJZERO(obj)
Definition shared.h:178
s_sample_t * sample
Definition s_local.h:52
int count
Definition s_local.h:54
float atten
Definition s_local.h:53
vec3_t org
Definition s_local.h:51
char * name
Definition s_local.h:42
int lastPlayed
Definition s_local.h:43
Mix_Chunk * chunk
Definition s_local.h:45
vec_t vec3_t[3]
Definition ufotypes.h:39
#define VectorSubtract(a, b, dest)
Definition vector.h:45
#define VectorCopy(src, dest)
Definition vector.h:51
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition vector.h:44