TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
TorcsSound.cpp
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2/***************************************************************************
3 file : TorcsSound.cpp
4 created : Tue Apr 5 19:57:35 CEST 2005
5 copyright : (C) 2005 Christos Dimitrakakis, Bernhard Wymann
6 email : dimitrak@idiap.ch
7 version : $Id$
8
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20#include "TorcsSound.h"
21#include "SoundInterface.h"
22
23
25void TorcsSound::setVolume(float vol)
26{
27 this->volume = vol;
28}
29
31{
32 this->pitch = pitch;
33}
34
36{
37 this->lowpass = lp;
38}
39
43 const char* filename,
44 int flags,
45 bool loop) : TorcsSound (flags)
46{
47 this->sched = sched;
48 this->loop = loop;
49 MAX_VOL = 1.0f;
50 sample = new slSample (filename, sched);
51 if (flags & ACTIVE_VOLUME) {
52 volume_env = new slEnvelope(1, SL_SAMPLE_ONE_SHOT);
53 }
54 if (flags & ACTIVE_PITCH) {
55 pitch_env = new slEnvelope(1, SL_SAMPLE_ONE_SHOT);
56 }
57 if (flags & ACTIVE_LP_FILTER) {
58 lowpass_env = new slEnvelope(1, SL_SAMPLE_ONE_SHOT);
59 }
60 if (loop) {
61 sched->loopSample (sample);
62 }
63 if (flags & ACTIVE_VOLUME) {
64 sched->addSampleEnvelope (sample, 0, VOLUME_SLOT, volume_env,
65 SL_VOLUME_ENVELOPE);
66 }
67 if (flags & ACTIVE_PITCH) {
68 sched->addSampleEnvelope (sample, 0, PITCH_SLOT, pitch_env,
69 SL_PITCH_ENVELOPE);
70 }
71 if (flags & ACTIVE_LP_FILTER) {
72 sched->addSampleEnvelope(sample, 0, FILTER_SLOT, lowpass_env,
73 SL_FILTER_ENVELOPE);
74 }
75 if (flags & ACTIVE_VOLUME) {
76 volume_env->setStep(0, 0.0f, 0.0f);
77 }
78 if (flags & ACTIVE_PITCH) {
79 pitch_env->setStep(0, 0.0f, 1.0f);
80 }
81 if (flags & ACTIVE_LP_FILTER) {
82 lowpass_env->setStep(0, 0.0, 1.0f);
83 }
84 volume = 0.0f;
85 pitch = 1.0f;
86 lowpass = 1.0f;
87 playing = false;
88 paused = false;
89}
90
91
94{
95 sched->stopSample(sample);
96 if (flags & ACTIVE_VOLUME) {
97 sched->addSampleEnvelope(sample, 0, VOLUME_SLOT, NULL,
98 SL_NULL_ENVELOPE);
99 delete volume_env;
100 }
101 if (flags & ACTIVE_PITCH) {
102 sched->addSampleEnvelope(sample, 0, PITCH_SLOT, NULL,
103 SL_NULL_ENVELOPE);
104 delete pitch_env;
105 }
106 if (flags & ACTIVE_LP_FILTER) {
107 sched->addSampleEnvelope(sample, 0, FILTER_SLOT, NULL,
108 SL_NULL_ENVELOPE);
109 delete lowpass_env;
110 }
111 delete sample;
112}
113
118{
119 if (vol > MAX_VOL) {
120 vol = MAX_VOL;
121 }
122 this->volume = vol;
123
124 if (loop==false) {
125 sample->adjustVolume (vol);
126 }
127}
128
130{
131 start();
132}
133
135{
136 // TODO: consistency check?
137 if (loop) {
138 if (playing == false) {
139 playing = true;
140 sched->loopSample (sample);
141 }
142 } else {
143 playing = true;
144 sched->playSample (sample);
145 }
146}
147
149{
150 if (playing == true) {
151 playing = false;
152 sched->stopSample (sample);
153 }
154}
155
157{
158 sched->resumeSample (sample);
159 paused = false;
160}
161
163{
164 sched->pauseSample (sample);
165 paused = true;
166}
167
168
169
175{
176 if (flags & ACTIVE_VOLUME) {
177 volume_env->setStep(0, 0.0f, volume);
178 }
179 if (flags & ACTIVE_PITCH) {
180 pitch_env->setStep(0, 0.0f, pitch);
181
182 }
183 if (flags & ACTIVE_LP_FILTER) {
184 lowpass_env->setStep(0, 0.0f, lowpass);
185 }
186}
187
190{
191 a = 0.0;
192 f = 1.0;
193 lp = 1.0;
194}
195
200
202{
203 // Get relative speed/position vector
204 sgVec3 u;
205 sgVec3 p;
206 float u_rel = 0.0f;
207 float u_rel_src = 0.0f;
208 float u_rel_lis = 0.0f;
209 float p_rel = 0.0f;
210 int i;
211 for (i=0; i<3; i++) {
212 u[i] = u_src[i] - u_lis[i];
213 p[i] = p_src[i] - p_lis[i];
214 p_rel += p[i]*p[i];
215 }
216
217 a = 1.0;
218 f = 1.0f;
219 lp = 1.0f;
220
221 // Only the vector component on the LOV is significant
222 // u_rel = sqrt(u_rel);
223 p_rel = 0.01f + sqrt(p_rel);
224 float p_cosx = p[0]/p_rel;
225 float p_cosy = p[1]/p_rel;
226 float p_cosz = p[2]/p_rel;
227 float p_x_comp = u[0]*p_cosx;
228 float p_y_comp = u[1]*p_cosy;
229 float p_z_comp = u[2]*p_cosz;
230 float p_x_src = u_src[0]*p_cosx;
231 float p_y_src = u_src[1]*p_cosy;
232 float p_z_src = u_src[2]*p_cosz;
233 float p_x_lis = u_lis[0]*p_cosx;
234 float p_y_lis = u_lis[1]*p_cosy;
235 float p_z_lis = u_lis[2]*p_cosz;
236 u_rel = (p_y_comp + p_x_comp + p_z_comp);
237 u_rel_src = (p_y_src + p_x_src + p_z_src);
238 u_rel_lis = (p_y_lis + p_x_lis + p_z_lis);
239 if (fabs(u_rel)>=0.9f*SPEED_OF_SOUND) {
240 // Cut-off sound when relative speed approaches speed of sound.
241 a = 0.0f;
242 f = 1.0f;
243 lp = 1.0f;
244 } else {
245 // attenuate and filter sound with distance
246 // and shift pitch with speed
247 float ref = 5.0f;
248 float rolloff = 0.5f;
249 float atten = ref / ( ref + rolloff * (p_rel - ref));
250 //f = SPEED_OF_SOUND/(SPEED_OF_SOUND+u_rel);
251 f = (SPEED_OF_SOUND - u_rel_src)/(SPEED_OF_SOUND - u_rel_lis);
252 a = atten;
253 float atten_filter = MIN (atten, 1.0f);
254 lp = exp(atten_filter - 1.0f);
255 }
256
257}
258
259
262void SoundSource::setSource(sgVec3 p, sgVec3 u)
263{
264 for (int i=0; i<3; i++) {
265 p_src[i] = p[i];
266 u_src[i] = u[i];
267 }
268}
269
272void SoundSource::setListener (sgVec3 p, sgVec3 u)
273{
274 for (int i=0; i<3; i++) {
275 p_lis[i] = p[i];
276 u_lis[i] = u[i];
277 }
278}
279
280
286{
287
288 this->loop = loop;
289 this->flags = flags;
290 this->static_pool = static_pool;
291 volume = 0.0f;
292 pitch = 1.0f;
293 lowpass = 1.0f;
294 poolindex = -1;
295 itf = sitf;
296
297 MAX_DISTANCE = 10000.0f;
298 MAX_DISTANCE_LOW = 5.0f;
299 REFERENCE_DISTANCE = 5.0f;
300 ROLLOFF_FACTOR = 0.5f;
301
302 playing = false;
303 paused = false;
304
305 int i;
306 for (i = 0; i<3; i++) {
307 source_position[i] = 0.0f;
308 source_velocity[i] = 0.0f;
309 zeroes[i] = 0.0f;
310 }
311
312 //printf("SOUND, create source: %s -> %s\n", filename, (static_pool == true) ? "static" : "dynamic");
313
314 int error = alGetError();
315 if (error != AL_NO_ERROR) {
316 printf("Uncatched OpenAL Error on entry: %d with file %s\n", error, filename);
317 }
318
319 alGenBuffers (1, &buffer);
320 error = alGetError();
321 if (error != AL_NO_ERROR) {
322 printf("OpenAL Error: %d, alGenBuffers failed %s\n", error, filename);
323 is_enabled = false;
324 return;
325 }
326
327 ALvoid *wave = NULL;
328 ALsizei size;
329 ALsizei freq;
330 ALenum format;
331 ALboolean srcloop;
332
333 alutLoadWAVFile((ALbyte *) filename, &format, &wave, &size, &freq, &srcloop);
334 error = alGetError();
335 if (error != AL_NO_ERROR) {
336 printf("OpenAL Error: %d, could not load %s\n", error, filename);
337 if (alIsBuffer(buffer)) {
338 alDeleteBuffers(1, &buffer);
339 alGetError();
340 }
341 is_enabled = false;
342 return;
343 }
344
345 alBufferData (buffer, format, wave, size, freq);
346 error = alGetError();
347 if (error != AL_NO_ERROR) {
348 printf("OpenAL Error: %d, alBufferData %s\n", error, filename);
349 if (alIsBuffer(buffer)) {
350 alDeleteBuffers(1, &buffer);
351 alGetError();
352 }
353 is_enabled = false;
354 return;
355 }
356
357 alutUnloadWAV(format, wave, size, freq);
358 error = alGetError();
359 if (error != AL_NO_ERROR) {
360 printf("OpenAL Error: %d, alutUnloadWAV %s\n", error, filename);
361 }
362
363 if (!static_pool) {
364 is_enabled = true;
365 return;
366 }
367
368 if (!sitf->getStaticSource(&source)) {
369 is_enabled = false;
370 printf(" No static sources left: %s\n", filename);
371 if (alIsBuffer(buffer)) {
372 alDeleteBuffers(1, &buffer);
373 alGetError();
374 }
375 return;
376 } else {
377 is_enabled = true;
378 }
379
380 alSourcefv (source, AL_POSITION, source_position);
381 error = alGetError();
382 if (error != AL_NO_ERROR) {
383 printf("OpenAL Error: %d, alSourcefv AL_POSITION %s\n", error, filename);
384 }
385
386 alSourcefv (source, AL_VELOCITY, source_velocity);
387 error = alGetError();
388 if (error != AL_NO_ERROR) {
389 printf("OpenAL Error: %d, alSourcefv AL_VELOCITY %s\n", error, filename);
390 }
391
392 alSourcei (source, AL_BUFFER, buffer);
393 error = alGetError();
394 if (error != AL_NO_ERROR) {
395 printf("OpenAL Error: %d, alSourcei AL_BUFFER %s\n", error, filename);
396 }
397
398 alSourcei (source, AL_LOOPING, loop);
399 if (error != AL_NO_ERROR) {
400 printf("OpenAL Error: %d, alSourcei AL_LOOPING %s\n", error, filename);
401 }
402
403 alSourcef (source, AL_MAX_DISTANCE, MAX_DISTANCE);
404 if (error != AL_NO_ERROR) {
405 printf("OpenAL Error: %d, alSourcef AL_MAX_DISTANCE %s\n", error, filename);
406 }
407
408 alSourcef (source, AL_REFERENCE_DISTANCE, REFERENCE_DISTANCE);
409 if (error != AL_NO_ERROR) {
410 printf("OpenAL Error: %d, alSourcef AL_REFERENCE_DISTANCE %s\n", error, filename);
411 }
412
413 alSourcef (source, AL_ROLLOFF_FACTOR, ROLLOFF_FACTOR);
414 if (error != AL_NO_ERROR) {
415 printf("OpenAL Error: %d, alSourcef AL_ROLLOFF_FACTOR %s\n", error, filename);
416 }
417
418 alSourcef (source, AL_GAIN, 0.0f);
419 if (error != AL_NO_ERROR) {
420 printf("OpenAL Error: %d, alSourcef AL_GAIN %s\n", error, filename);
421 }
422}
423
425{
426 if (alIsSource(source)) {
427 alSourceStop (source);
428 alDeleteSources(1, &source);
429 }
430 if (alIsBuffer(buffer)) {
431 alDeleteBuffers(1, &buffer);
432 }
433}
434
436{
437 this->volume = vol;
438}
439
441{
442 this->pitch = pitch;
443}
444
446{
447 this->lowpass = lp;
448}
449
450
452{
453 if (static_pool) {
454 if (is_enabled) {
455 alSourcef (source, AL_REFERENCE_DISTANCE, dist);
456 }
457 } else {
458 if (itf->getSourcePool()->isSourceActive(this, &poolindex)) {
459 alSourcef (source, AL_REFERENCE_DISTANCE, dist);
460 REFERENCE_DISTANCE = dist;
461 }
462 }
463}
464
465
466void OpenalTorcsSound::setSource (sgVec3 p, sgVec3 u)
467{
468 for (int i=0; i<3; i++) {
469 source_position[i] = p[i];
470 source_velocity[i] = u[i];
471 }
472}
473
474
475void OpenalTorcsSound::getSource(sgVec3 p, sgVec3 u)
476{
477 for (int i=0; i<3; i++) {
478 p[i] = source_position[i];
479 u[i] = source_velocity[i];
480 }
481}
482
483
485{
486 start();
487}
488
490{
491 if (static_pool) {
492 if (is_enabled) {
493 if (playing==false) {
494 if (loop) {
495 playing = true;
496 }
497 alSourcePlay (source);
498 }
499 }
500 } else {
501 // shared source.
502 bool needs_init;
503 if (itf->getSourcePool()->getSource(this, &source, &needs_init, &poolindex)) {
504 if (needs_init) {
505 // Setup source.
506 alSourcefv (source, AL_POSITION, source_position);
507 alSourcefv (source, AL_VELOCITY, source_velocity);
508 alSourcei (source, AL_BUFFER, buffer);
509 alSourcei (source, AL_LOOPING, loop);
510 alSourcef (source, AL_MAX_DISTANCE, MAX_DISTANCE);
511 alSourcef (source, AL_REFERENCE_DISTANCE, REFERENCE_DISTANCE);
512 alSourcef (source, AL_ROLLOFF_FACTOR, ROLLOFF_FACTOR);
513 alSourcef (source, AL_GAIN, 0.0f);
514 }
515
516 // play
517 if (playing==false) {
518 if (loop) {
519 playing = true;
520 }
521 alSourcePlay (source);
522 }
523 }
524 }
525}
526
527
529{
530 if (static_pool) {
531 if (is_enabled) {
532 if (playing==true) {
533 playing = false;
534 alSourceStop (source);
535 }
536 }
537 } else {
538 // Shared source.
539 if (itf->getSourcePool()->releaseSource(this, &poolindex)) {
540 if (playing==true) {
541 playing = false;
542 alSourceStop (source);
543 }
544 }
545 }
546}
547
549{
550 if (paused==true) {
551 paused = false;
552 }
553}
554
555
557{
558 if (paused==false) {
559 paused = true;
560 }
561}
562
564{
565 ALfloat zero_velocity[3] = {0.0f, 0.0f, 0.0f};
566 if (static_pool) {
567 if (is_enabled) {
568 alSourcefv (source, AL_POSITION, source_position);
569 alSourcefv (source, AL_VELOCITY, zero_velocity);
570 alSourcef (source, AL_PITCH, pitch);
571 alSourcef (source, AL_GAIN, volume);
572 }
573 } else {
574 if (itf->getSourcePool()->isSourceActive(this, &poolindex)) {
575 alSourcefv (source, AL_POSITION, source_position);
576 alSourcefv (source, AL_VELOCITY, zero_velocity);
577 alSourcef (source, AL_PITCH, pitch);
578 alSourcef (source, AL_GAIN, volume);
579 }
580 }
581}
582
583
static Point p[4]
Definition Convex.cpp:54
#define PITCH_SLOT
Definition TorcsSound.h:24
#define FILTER_SLOT
Definition TorcsSound.h:25
#define VOLUME_SLOT
Definition TorcsSound.h:23
virtual bool getStaticSource(ALuint *source)
virtual void pause()
ALuint buffer
buffer id
Definition TorcsSound.h:160
virtual void getSource(sgVec3 p, sgVec3 u)
bool static_pool
dynamic or static source assignment?
Definition TorcsSound.h:174
virtual void setLPFilter(float lp)
OpenalSoundInterface * itf
Handle to the interface.
Definition TorcsSound.h:173
ALfloat zeroes[3]
just a vector of 0s
Definition TorcsSound.h:164
ALfloat source_velocity[3]
source velocity
Definition TorcsSound.h:163
ALfloat REFERENCE_DISTANCE
reference distance for sound
Definition TorcsSound.h:170
ALfloat source_position[3]
source position
Definition TorcsSound.h:162
virtual void update()
virtual void setSource(sgVec3 p, sgVec3 u)
virtual void setReferenceDistance(float dist)
bool is_enabled
is it available at all?
Definition TorcsSound.h:175
ALfloat MAX_DISTANCE
maximum allowed distance
Definition TorcsSound.h:168
OpenalTorcsSound(const char *filename, OpenalSoundInterface *sitf, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)
Create a new torcs sound.
ALuint source
source id
Definition TorcsSound.h:161
virtual void play()
ALfloat ROLLOFF_FACTOR
how fast we need to roll off
Definition TorcsSound.h:171
virtual void setPitch(float pitch)
virtual ~OpenalTorcsSound()
virtual void stop()
virtual void resume()
int poolindex
which pool the sound is assigned to
Definition TorcsSound.h:172
virtual void start()
ALfloat MAX_DISTANCE_LOW
maximum allowed distance
Definition TorcsSound.h:169
virtual void setVolume(float vol)
bool paused
sound is paused
Definition TorcsSound.h:102
virtual void update()
Update the plib sounds.
virtual void play()
Start the sample.
slEnvelope * pitch_env
pitch envelope
Definition TorcsSound.h:98
virtual void resume()
Resume a paused sample.
PlibTorcsSound(slScheduler *sched, const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false)
Create a new PLib sound.
slEnvelope * volume_env
volume envelope
Definition TorcsSound.h:97
virtual void stop()
Stop the sample.
slSample * sample
sample data
Definition TorcsSound.h:96
slEnvelope * lowpass_env
low pass filter envelope
Definition TorcsSound.h:99
bool playing
Sound is playing.
Definition TorcsSound.h:101
virtual void pause()
Pause a sample.
virtual ~PlibTorcsSound()
Destructor.
slScheduler * sched
plib sl scheduler (see sl.h)
Definition TorcsSound.h:100
virtual void setVolume(float vol)
Set the volume.
virtual void start()
Start the sample.
float a
Environmental attenuation.
Definition TorcsSound.h:147
float lp
Environmental filtering.
Definition TorcsSound.h:149
sgVec3 p_lis
listener position for this source
Definition TorcsSound.h:143
sgVec3 u_src
source velocity;
Definition TorcsSound.h:146
float f
Environmental frequency shift.
Definition TorcsSound.h:148
SoundSource()
Create a sound source.
sgVec3 p_src
source position
Definition TorcsSound.h:145
void update()
Calculate environmental parameters for current situation.
void setSource(sgVec3 p, sgVec3 u)
Set source position and velocity.
void setListener(sgVec3 p, sgVec3 u)
Set listener position and velocity.
sgVec3 u_lis
listener velocity for this source
Definition TorcsSound.h:144
float MAX_VOL
Maximum volume.
Definition TorcsSound.h:57
float volume
Current volume.
Definition TorcsSound.h:58
TorcsSound(int flags=(ACTIVE_VOLUME|ACTIVE_PITCH))
Consruct a sound.
Definition TorcsSound.h:64
virtual void setPitch(float pitch)
Set the pitch.
bool loop
Whether it's a looping sound.
Definition TorcsSound.h:61
int flags
Flags relating to what effects are to be used.
Definition TorcsSound.h:56
virtual void setLPFilter(float lp)
Set the filter.
float pitch
Current pitch.
Definition TorcsSound.h:59
virtual void setVolume(float vol)
Set the volume.
float lowpass
Current low pass filter.
Definition TorcsSound.h:60
#define ACTIVE_LP_FILTER
#define ACTIVE_PITCH
#define ACTIVE_VOLUME
#define SPEED_OF_SOUND
#define MIN(x, y)
Definition tgf.h:56