TORCS  1.3.9
The Open Racing Car Simulator
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 
25 void TorcsSound::setVolume(float vol)
26 {
27  this->volume = vol;
28 }
30 void TorcsSound::setPitch(float pitch)
31 {
32  this->pitch = pitch;
33 }
36 {
37  this->lowpass = lp;
38 }
39 
42 PlibTorcsSound::PlibTorcsSound(slScheduler* sched,
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 }
130 {
131  start();
132 }
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 }
149 {
150  if (playing == true) {
151  playing = false;
152  sched->stopSample (sample);
153  }
154 }
157 {
158  sched->resumeSample (sample);
159  paused = false;
160 }
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 
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 
262 void 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 
272 void 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 
285 OpenalTorcsSound::OpenalTorcsSound(const char* filename, OpenalSoundInterface* sitf, int flags, bool loop, bool static_pool)
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 
440 void OpenalTorcsSound::setPitch(float pitch)
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 
466 void 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 
475 void 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 
virtual void setVolume(float vol)
Set the volume.
Definition: TorcsSound.cpp:117
virtual void setLPFilter(float lp)
Definition: TorcsSound.cpp:445
virtual void stop()
Stop the sample.
Definition: TorcsSound.cpp:148
SoundSource()
Create a sound source.
Definition: TorcsSound.cpp:189
bool static_pool
dynamic or static source assignment?
Definition: TorcsSound.h:174
ALfloat MAX_DISTANCE_LOW
maximum allowed distance
Definition: TorcsSound.h:169
sgVec3 u_src
source velocity;
Definition: TorcsSound.h:146
virtual void setLPFilter(float lp)
Set the filter.
Definition: TorcsSound.cpp:35
void update()
Calculate environmental parameters for current situation.
Definition: TorcsSound.cpp:201
virtual void pause()
Definition: TorcsSound.cpp:556
#define FILTER_SLOT
Definition: TorcsSound.h:25
slEnvelope * volume_env
volume envelope
Definition: TorcsSound.h:97
virtual void update()
Update the plib sounds.
Definition: TorcsSound.cpp:174
virtual void setPitch(float pitch)
Set the pitch.
Definition: TorcsSound.cpp:30
slSample * sample
sample data
Definition: TorcsSound.h:96
#define SPEED_OF_SOUND
Definition: sound_defines.h:10
virtual void update()
Definition: TorcsSound.cpp:563
bool getSource(TorcsSound *sound, ALuint *source, bool *needs_init, int *index)
virtual void start()
Definition: TorcsSound.cpp:489
bool loop
Whether it&#39;s a looping sound.
Definition: TorcsSound.h:61
virtual void setVolume(float vol)
Definition: TorcsSound.cpp:435
void setSource(sgVec3 p, sgVec3 u)
Set source position and velocity.
Definition: TorcsSound.cpp:262
#define ACTIVE_LP_FILTER
Definition: sound_defines.h:16
int flags
Flags relating to what effects are to be used.
Definition: TorcsSound.h:56
slScheduler * sched
plib sl scheduler (see sl.h)
Definition: TorcsSound.h:100
ALfloat ROLLOFF_FACTOR
how fast we need to roll off
Definition: TorcsSound.h:171
ALfloat REFERENCE_DISTANCE
reference distance for sound
Definition: TorcsSound.h:170
OpenalTorcsSound(const char *filename, OpenalSoundInterface *sitf, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)
Create a new torcs sound.
Definition: TorcsSound.cpp:285
slEnvelope * pitch_env
pitch envelope
Definition: TorcsSound.h:98
int poolindex
which pool the sound is assigned to
Definition: TorcsSound.h:172
#define VOLUME_SLOT
Definition: TorcsSound.h:23
virtual bool getStaticSource(ALuint *source)
sgVec3 p_src
source position
Definition: TorcsSound.h:145
void setListener(sgVec3 p, sgVec3 u)
Set listener position and velocity.
Definition: TorcsSound.cpp:272
float f
Environmental frequency shift.
Definition: TorcsSound.h:148
virtual void play()
Start the sample.
Definition: TorcsSound.cpp:129
slEnvelope * lowpass_env
low pass filter envelope
Definition: TorcsSound.h:99
PlibTorcsSound(slScheduler *sched, const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false)
Create a new PLib sound.
Definition: TorcsSound.cpp:42
float a
Environmental attenuation.
Definition: TorcsSound.h:147
sgVec3 p_lis
listener position for this source
Definition: TorcsSound.h:143
virtual void setVolume(float vol)
Set the volume.
Definition: TorcsSound.cpp:25
ALuint source
source id
Definition: TorcsSound.h:161
ALfloat MAX_DISTANCE
maximum allowed distance
Definition: TorcsSound.h:168
static Point p[4]
Definition: Convex.cpp:54
virtual void resume()
Resume a paused sample.
Definition: TorcsSound.cpp:156
bool playing
Sound is playing.
Definition: TorcsSound.h:101
float volume
Current volume.
Definition: TorcsSound.h:58
#define ACTIVE_VOLUME
Definition: sound_defines.h:14
virtual void stop()
Definition: TorcsSound.cpp:528
virtual void play()
Definition: TorcsSound.cpp:484
virtual void start()
Start the sample.
Definition: TorcsSound.cpp:134
sgVec3 u_lis
listener velocity for this source
Definition: TorcsSound.h:144
#define PITCH_SLOT
Definition: TorcsSound.h:24
float MAX_VOL
Maximum volume.
Definition: TorcsSound.h:57
virtual void setPitch(float pitch)
Definition: TorcsSound.cpp:440
bool is_enabled
is it available at all?
Definition: TorcsSound.h:175
ALfloat source_velocity[3]
source velocity
Definition: TorcsSound.h:163
float pitch
Current pitch.
Definition: TorcsSound.h:59
float lowpass
Current low pass filter.
Definition: TorcsSound.h:60
ALfloat source_position[3]
source position
Definition: TorcsSound.h:162
virtual void resume()
Definition: TorcsSound.cpp:548
virtual SharedSourcePool * getSourcePool(void)
float lp
Environmental filtering.
Definition: TorcsSound.h:149
virtual void pause()
Pause a sample.
Definition: TorcsSound.cpp:162
virtual void setSource(sgVec3 p, sgVec3 u)
Definition: TorcsSound.cpp:466
virtual ~OpenalTorcsSound()
Definition: TorcsSound.cpp:424
OpenalSoundInterface * itf
Handle to the interface.
Definition: TorcsSound.h:173
Definition: Endpoint.h:36
bool isSourceActive(TorcsSound *sound, int *index)
#define ACTIVE_PITCH
Definition: sound_defines.h:15
virtual void getSource(sgVec3 p, sgVec3 u)
Definition: TorcsSound.cpp:475
bool paused
sound is paused
Definition: TorcsSound.h:102
ALfloat zeroes[3]
just a vector of 0s
Definition: TorcsSound.h:164
A generic TORCS sound.
Definition: TorcsSound.h:53
bool releaseSource(TorcsSound *sound, int *index)
virtual void setReferenceDistance(float dist)
Definition: TorcsSound.cpp:451
ALuint buffer
buffer id
Definition: TorcsSound.h:160
virtual ~PlibTorcsSound()
Destructor.
Definition: TorcsSound.cpp:93