UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
s_mix.cpp
Go to the documentation of this file.
1 
6 /*
7 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 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"
29 #include "../battlescape/cl_camera.h"
30 #include "../battlescape/cl_localentity.h"
31 #include "../battlescape/cl_battlescape.h"
32 
33 #include "s_mix.h"
34 #include "s_sample.h"
35 #include "s_main.h"
36 
41 static 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 
55 void S_FreeChannel (int c)
56 {
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 
96 void 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 */
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 
134 void 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 
184 void 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 }
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
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition: mathlib.cpp:434
#define VectorCopy(src, dest)
Definition: vector.h:51
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_StartLocalSample(const char *name, float relVolume)
Plays a sample without spatialization.
Definition: s_mix.cpp:184
s_sample_t * S_LoadSample(const char *soundFile)
Loads and registers a sound file for later use.
Definition: s_main.cpp:342
voidpf uLong int origin
Definition: ioapi.h:45
int sampleRepeatRate
Definition: s_local.h:65
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
float atten
Definition: s_local.h:53
Specifies sound API?
bool initialized
Definition: s_local.h:70
cvar_t * snd_distance_scale
Definition: s_main.cpp:43
float value
Definition: cvar.h:80
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
vec3_t right
Definition: s_local.h:61
int count
Definition: s_local.h:54
s_channel_t channels[MAX_CHANNELS]
Definition: s_local.h:63
#define todeg
Definition: mathlib.h:51
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition: vector.h:44
#define OBJZERO(obj)
Definition: shared.h:178
s_env_t s_env
Definition: s_main.cpp:40
int lastPlayed
Definition: s_local.h:43
clientBattleScape_t cl
cvar_t * snd_volume
Definition: s_main.cpp:42
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
char * name
Definition: s_local.h:42
QGL_EXTERN GLint i
Definition: r_gl.h:113
void S_SpatializeChannel(const s_channel_t *ch)
Set distance and stereo panning for the specified channel.
Definition: s_mix.cpp:64
vec3_t org
Definition: s_local.h:51
vec_t VectorNormalize(vec3_t v)
Calculate unit vector for a given vec3_t.
Definition: mathlib.cpp:745
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
Specifies sound API?
static int S_AllocChannel(void)
Searches a channel with no sample applied yet.
Definition: s_mix.cpp:41
vec_t vec3_t[3]
Definition: ufotypes.h:39
#define SOUND_ATTN_NORM
Definition: common.h:186
Mix_Chunk * chunk
Definition: s_local.h:45
s_sample_t * sample
Definition: s_local.h:52
vec3_t camorg
Definition: cl_camera.h:32
#define DEBUG_SOUND
Definition: defines.h:63
#define MAX_CHANNELS
the sound environment
Definition: s_local.h:58
void S_FreeChannel(int c)
Callback that is called when a channel finished playing.
Definition: s_mix.cpp:55
#define VectorSubtract(a, b, dest)
Definition: vector.h:45
int CL_Milliseconds(void)
Definition: cl_main.cpp:1208