TORCS  1.3.9
The Open Racing Car Simulator
SoundInterface.h
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 /***************************************************************************
3  file : SoundInterface.h
4  created : Tue Apr 5 19:57:35 CEST 2005
5  copyright : (C) 2005-2024 Christos Dimitrakakis, Bernhard Wymann
6  email : berniw@bluewin.ch
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #ifndef SOUND_INTERFACE_H
20 #define SOUND_INTERFACE_H
21 
22 #define USE_OPENAL 1
23 
24 #undef SOUND_LOG
25 
26 
27 #ifdef SOUND_LOG
28 #define logmsg printf ("# "); printf
29 #else
30 #define logmsg empty_log
31 static void empty_log(const char* s, ...)
32 {
33 }
34 #endif
35 
36 
37 
38 #include <plib/sl.h>
39 #include <plib/sg.h>
40 #include <raceman.h>
41 #include <vector>
42 
43 #include "TorcsSound.h"
44 //#include "grsound.h"
45 #include "QSoundChar.h"
46 
47 
48 #define VOLUME_CUTOFF 0.001f
49 
50 
51 class CarSoundData;
52 
63 typedef struct QueueSoundMap_ {
66  float max_vol;
67  int id;
69 
73 };
74 
76 typedef struct SoundPri_ {
77  float a;
78  int id;
79 } SoundPri;
80 
83  protected:
84  float sampling_rate;
85  int n_channels;
102 
103  std::vector<TorcsSound*> sound_list;
105 
115 
118  QueueSoundMap* smap,
119  int n_cars);
120 
125  QueueSoundMap* smap);
126 
127  public:
130 
132  virtual ~SoundInterface() {}
133 
135  virtual void setNCars(int n_cars) = 0;
136 
138  virtual TorcsSound* addSample (const char* filename,
139  int flags = (ACTIVE_VOLUME|ACTIVE_PITCH),
140  bool loop = false, bool static_pool = true) = 0;
141 
143  virtual void initSharedSourcePool() {}
144 
145  void setSkidSound (const char* sound_name)
146  {
147  for (int i=0; i<4; i++) {
148  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
149  skid_sound[i] = sound;
150  }
151 
152  }
153  void setRoadRideSound (const char* sound_name)
154  {
155  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
156  road_ride_sound = sound;
157  }
158  void setGrassRideSound (const char* sound_name)
159  {
160  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
161  grass_ride_sound = sound;
162  }
163  void setCurbRideSound (const char* sound_name)
164  {
165  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
166  curb_ride_sound = sound;
167  }
168  void setGrassSkidSound (const char* sound_name)
169  {
170  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
171  grass_skid_sound = sound;
172  }
173  void setMetalSkidSound (const char* sound_name)
174  {
175  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
176  metal_skid_sound = sound;
177  }
178  void setAxleSound (const char* sound_name)
179  {
180  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
181  axle_sound = sound;
182  }
183  void setTurboSound (const char* sound_name)
184  {
185  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
186  turbo_sound = sound;
187  }
188  void setBackfireLoopSound (const char* sound_name)
189  {
190  TorcsSound* sound = addSample (sound_name, ACTIVE_VOLUME|ACTIVE_PITCH, true);
191  backfire_loop_sound = sound;
192  }
193  void setCrashSound (const char* sound_name, int index)
194  {
195  TorcsSound* sound = addSample (sound_name, 0, false);
196  assert (index>=0 && index<NB_CRASH_SOUND);
197  crash_sound[index] = sound;
198  }
199 
200  void setBangSound (const char* sound_name)
201  {
202  TorcsSound* sound = addSample (sound_name, 0, false);
203  bang_sound = sound;
204  }
205 
206  void setBottomCrashSound (const char* sound_name)
207  {
208  TorcsSound* sound = addSample (sound_name, 0, false);
209  bottom_crash_sound = sound;
210  }
211 
212  void setBackfireSound (const char* sound_name)
213  {
214  TorcsSound* sound = addSample (sound_name, 0, false);
215  backfire_sound = sound;
216  }
217 
218  void setGearChangeSound (const char* sound_name)
219  {
220  TorcsSound* sound = addSample (sound_name, 0, false);
221  gear_change_sound = sound;
222  }
225  int n_cars, sgVec3 p_obs, sgVec3 u_obs,
226  sgVec3 c_obs = NULL, sgVec3 a_obs = NULL)
227  {
228  // do nothing
229  }
230 
231  virtual void muteForMenu() {}
232  virtual float getGlobalGain() {return 1.0f;}
233  virtual void setGlobalGain(float g)
234  {
235  fprintf (stderr, "Warning, gain setting not supported\n");
236  }
237 
238 };
239 
240 
241 
244  typedef struct SoundChar_ {
245  float f; //frequency modulation
246  float a; //amplitude modulation
247  } SoundChar;
248  protected:
249  slScheduler* sched;
250  std::vector<TorcsSound*> sound_list;
254  void DopplerShift (SoundChar* sound, float* p_src, float* u_src, float* p, float* u);
256  float global_gain;
257  public:
259  virtual ~PlibSoundInterface();
260  virtual void setNCars(int n_cars);
261  virtual slScheduler* getScheduler();
262  virtual TorcsSound* addSample (const char* filename, int flags = (ACTIVE_VOLUME|ACTIVE_PITCH), bool loop = false, bool static_pool = true);
263  virtual void update(CarSoundData** car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs = NULL, sgVec3 a_obs = NULL);
264  virtual float getGlobalGain() {return global_gain;}
265  virtual void setGlobalGain(float g)
266  {
267  global_gain = 0.5f*g;
268  logmsg ("Setting gain to %f\n", global_gain);
269  }
270 
271 };
272 
273 
274 
276 
277 class SharedSourcePool;
278 
280  typedef struct SoundChar_ {
281  float f; //frequency modulation
282  float a; //amplitude modulation
283  } SoundChar;
284  protected:
287  ALCcontext* cc;
288  ALCdevice* dev;
289  float global_gain;
295  static const int OSI_MIN_DYNAMIC_SOURCES;
296 
297  void DopplerShift (SoundChar* sound, float* p_src, float* u_src, float* p, float* u);
299 
300  public:
302  virtual ~OpenalSoundInterface();
303  virtual void setNCars(int n_cars);
304  virtual TorcsSound* addSample (const char* filename,
305  int flags = (ACTIVE_VOLUME|ACTIVE_PITCH),
306  bool loop = false, bool static_pool = true);
307  virtual void update(CarSoundData** car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs, sgVec3 a_obs);
308  virtual void muteForMenu();
309  virtual float getGlobalGain() { return global_gain; }
310  virtual void initSharedSourcePool();
311  virtual void setGlobalGain(float g)
312  {
313  global_gain = 0.5f*g;
314  logmsg ("Setting gain to %f\n", global_gain);
315  }
316  virtual bool getStaticSource(ALuint *source);
317 
318  virtual SharedSourcePool* getSourcePool(void) { return sourcepool; }
319 
320 
321 };
322 
323 
324 int sortSndPriority(const void* a, const void* b);
325 
326 
327 struct sharedSource {
328  ALuint source;
330  bool in_use;
331 };
332 
333 
335  public:
337  pool = new sharedSource[nbsources];
338  int i;
339  for (i = 0; i < nbsources; i++) {
340  pool[i].currentOwner = NULL;
341  pool[i].in_use = false;
342  alGenSources(1, &(pool[i].source));
343  int error = alGetError();
344  if (error != AL_NO_ERROR) {
345  printf("OpenAL error, allocating dynamic source index %d\n", i);
346  this->nbsources = i;
347  break;
348  }
349  }
350  printf(" Dynamic Sources: requested: %d, created: %d\n", nbsources, this->nbsources);
351  }
352 
353  virtual ~SharedSourcePool() {
354  int i;
355  for (i = 0; i < nbsources; i++) {
356  alDeleteSources(1, &(pool[i].source));
357  alGetError();
358  }
359  delete [] pool;
360  }
361 
362  bool getSource(TorcsSound* sound, ALuint* source, bool* needs_init, int* index) {
363  if (*index >= 0 && *index < nbsources) {
364  if (sound == pool[*index].currentOwner) {
365  // Resurrect source from pool.
366  *source = pool[*index].source;
367  *needs_init = false;
368  pool[*index].in_use = true;
369  return true;
370  }
371  }
372 
373  // TODO: Implement free list with ring buffer or whatever data structure
374  // to go from O(n) to O(1). If the ordering is done well it will automatically
375  // result in LRU (least recently used).
376  int i, firstfree = -1;
377  for (i = 0; i < nbsources; i++) {
378  if (pool[i].in_use == false && firstfree < 0) {
379  firstfree = i;
380  break;
381  }
382  }
383 
384  if (firstfree < 0) {
385  // No free source.
386  return false;
387  }
388 
389  pool[firstfree].currentOwner = sound;
390  pool[firstfree].in_use = true;
391  *source = pool[firstfree].source;
392  *needs_init = true;
393  *index = firstfree;
394  return true;
395  }
396 
397  bool releaseSource(TorcsSound* sound, int* index) {
398  if (*index >= 0 && *index < nbsources) {
399  if (sound == pool[*index].currentOwner) {
400  pool[*index].in_use = false;
401  return true;
402  }
403  }
404  return false;
405  }
406 
407  bool isSourceActive(TorcsSound* sound, int* index) {
408  if (*index >= 0 && *index < nbsources &&
409  sound == pool[*index].currentOwner &&
410  true == pool[*index].in_use)
411  {
412  return true;
413  } else {
414  return false;
415  }
416  }
417 
418  int getNbSources(void) { return nbsources; }
419 
420  protected:
423 };
424 
425 
426 
427 #endif /* SOUND_INTERFACE_H */
void setBackfireSound(const char *sound_name)
SoundPriState
Current state of sound.
void setRoadRideSound(const char *sound_name)
Sound source management.
Definition: TorcsSound.h:141
virtual float getGlobalGain()
float a
amplitude
virtual ~SharedSourcePool()
int id
car ID.
virtual void setGlobalGain(float g)
void setSkidSound(const char *sound_name)
sharedSource * pool
static CarSoundData ** car_sound_data
Definition: grsound.cpp:38
void DopplerShift(SoundChar *sound, float *p_src, float *u_src, float *p, float *u)
virtual void update(CarSoundData **car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs=NULL, sgVec3 a_obs=NULL)
Update sound for a given observer.
TorcsSound * bang_sound
sounds when suspension fully compressed
QueueSoundMap axle
QueueSoundMap turbo
SharedSourcePool * sourcepool
int curCrashSnd
holds current crash sound used - the sound cycles
void setAxleSound(const char *sound_name)
int sortSndPriority(const void *a, const void *b)
A queue containing mappings between sounds and sound sources.
TorcsSound * bottom_crash_sound
bang when crashing from a great height
QSoundChar CarSoundData::* schar
The calculated sound characteristic.
virtual TorcsSound * addSample(const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)=0
Add a new sample - must be defined in children classes.
bool getSource(TorcsSound *sound, ALuint *source, bool *needs_init, int *index)
TorcsSound * curb_ride_sound
rolling on curb
void setBangSound(const char *sound_name)
virtual ~SoundInterface()
Destructor - does nothing.
void DopplerShift(SoundChar *sound, float *p_src, float *u_src, float *p, float *u)
Manages the source sound of each individual car.
Definition: CarSoundData.h:25
static void empty_log(const char *s,...)
void setGrassSkidSound(const char *sound_name)
void setTurboSound(const char *sound_name)
void setBackfireLoopSound(const char *sound_name)
TorcsSound * backfire_loop_sound
exhaust backfire sound
virtual TorcsSound * addSample(const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)
void setCurbRideSound(const char *sound_name)
TorcsSound * currentOwner
void SetMaxSoundCar(CarSoundData **car_sound_data, QueueSoundMap *smap)
Using the smap->id, get the appropriate entry in car_sound_data and call apprioriate methods for smap...
QueueSoundMap grass_skid
SoundSource * car_src
TorcsSound * grass_skid_sound
skidding on dirt/grass
TorcsSound * turbo_sound
turbo spinning sound
virtual bool getStaticSource(ALuint *source)
QueueSoundMap grass
virtual TorcsSound * addSample(const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)
TorcsSound * road_ride_sound
rolling on normal road
#define logmsg
void setMetalSkidSound(const char *sound_name)
virtual void update(CarSoundData **car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs, sgVec3 a_obs)
virtual slScheduler * getScheduler()
virtual void update(CarSoundData **car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs=NULL, sgVec3 a_obs=NULL)
QueueSoundMap backfire_loop
static const int OSI_MIN_DYNAMIC_SOURCES
Define this to use the OpenAL Doppler.
SoundSource tyre_src[4]
struct PlibSoundInterface::SoundChar_ SoundChar
int n_channels
number of channels
TorcsSound * snd
The raw sound.
slScheduler * sched
SoundPri * engpri
the engine priority, used for sorting
static Point p[4]
Definition: Convex.cpp:54
virtual void SetMaxSoundCar(CarSoundData **car_sound_data, QueueSoundMap *smap)
#define ACTIVE_VOLUME
Definition: sound_defines.h:14
struct OpenalSoundInterface::SoundChar_ SoundChar
OpenalSoundInterface(float sampling_rate, int n_channels)
virtual float getGlobalGain()
void SortSingleQueue(CarSoundData **car_sound_data, QueueSoundMap *smap, int n_cars)
Find the max amplitude sound in car_sound_data and put it in smap.
struct SoundPri_ SoundPri
Sound priority, used to sort cars according to amplitude attenuation.
void setBottomCrashSound(const char *sound_name)
TorcsSound * backfire_sound
one-off backfire sound
QueueSoundMap road
The following are mappings for sound prioritisation.
This is the race information structures.
float sampling_rate
sampling rate
SoundSource * car_src
std::vector< TorcsSound * > sound_list
keeps track of sounds used
virtual void setGlobalGain(float g)
virtual void setNCars(int n_cars)
TorcsSound * gear_change_sound
sound when changing gears
void setGearChangeSound(const char *sound_name)
struct QueueSoundMap_ QueueSoundMap
A queue containing mappings between sounds and sound sources.
#define NB_CRASH_SOUND
Definition: sound_defines.h:11
virtual void initSharedSourcePool()
initialised the pool of shared sources
int getNbSources(void)
void setCrashSound(const char *sound_name, int index)
SharedSourcePool(int nbsources)
virtual void initSharedSourcePool()
int n_engine_sounds
number of simultaneous engines
Sound interface.
virtual SharedSourcePool * getSourcePool(void)
std::vector< TorcsSound * > sound_list
SoundInterface(float sampling_rate, int n_channels)
Make a new sound interface.
TorcsSound * crash_sound[NB_CRASH_SOUND]
list of crash sounds
void setGrassRideSound(const char *sound_name)
TorcsSound * metal_skid_sound
metal skidding on metal
TorcsSound * grass_ride_sound
rolling on dirt/grass
virtual float getGlobalGain()
PlibSoundInterface(float sampling_rate, int n_channels)
void SetMaxSoundCar(CarSoundData **car_sound_data, QueueSoundMap *smap)
virtual void setNCars(int n_cars)
bool isSourceActive(TorcsSound *sound, int *index)
#define ACTIVE_PITCH
Definition: sound_defines.h:15
virtual void muteForMenu()
SoundSource tyre_src[4]
virtual void setNCars(int n_cars)=0
Set the number of cars - must be defined in children classes.
virtual void setGlobalGain(float g)
QueueSoundMap metal_skid
float max_vol
Max.
TorcsSound * axle_sound
axle/gear spinning sound
TorcsSound * skid_sound[4]
set of skid sounds, one per tyre
A generic TORCS sound.
Definition: TorcsSound.h:53
int id
The id of the car producing the sound, used for retrieving doppler effects etc.
bool releaseSource(TorcsSound *sound, int *index)
QueueSoundMap curb
Sound priority, used to sort cars according to amplitude attenuation.
PLIB interface.