TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
OpenalSoundInterface.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : PlibSoundInterface.cpp
4 created : Thu Apr 7 04:21 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#include "SoundInterface.h"
20#include "CarSoundData.h"
21#include "TorcsSound.h"
22
23
25#undef USE_OPENAL_DOPPLER
26
28
29
30
32{
33 car_src = NULL;
34
35 ALfloat far_away[] = { 0.0f, 0.0f, 1000.0f };
36 ALfloat zeroes[] = { 0.0f, 0.0f, 0.0f };
37 ALfloat front[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f };
38 dev = alcOpenDevice( NULL );
39 if( dev == NULL ) {
40 throw ("Could not open device");
41 }
42
43 // Last zero is termination of the array, I think the current official beat SDK ignores that.
44 // ALCint attr[] = { ALC_MONO_SOURCES, 1024, ALC_STEREO_SOURCES, 0, 0};
45 cc = alcCreateContext( dev, NULL);
46 if(cc == NULL) {
47 alcCloseDevice( dev );
48 throw ("Could not create context.");
49 }
50
51 alcMakeContextCurrent( cc );
52 alcGetError(dev);
53 alGetError();
54
55 // Figure out the number of possible sources, watch out for an API update, perhaps
56 // one can get that easier later with al(c)GetInteger (I'm sure that there is no way to
57 // query this now) or even request a number with the context.
58 const int MAX_SOURCES = 1024;
59 int sources;
60 ALuint sourcelist[MAX_SOURCES];
61 for (sources = 0; sources < MAX_SOURCES; sources++) {
62 alGenSources(1, &sourcelist[sources]);
63 if (alGetError() != AL_NO_ERROR) {
64 break;
65 }
66 }
67
68 int clear;
69 for (clear = 0; clear < sources; clear++) {
70 if (alIsSource(sourcelist[clear])) {
71 alDeleteSources(1, &sourcelist[clear]);
72 if (alGetError() != AL_NO_ERROR) {
73 printf("Error in probing OpenAL sources.\n");
74 }
75 } else {
76 printf("Error in probing OpenAL sources.\n");
77 }
78 }
79
80 OSI_MAX_SOURCES = sources;
82
83 // Figure out the number of buffers.
84 int buffers;
85 ALuint bufferlist[MAX_SOURCES];
86 for (buffers = 0; buffers < MAX_SOURCES; buffers++) {
87 alGenBuffers(1, &bufferlist[buffers]);
88 if (alGetError() != AL_NO_ERROR) {
89 break;
90 }
91 }
92
93 for (clear = 0; clear < buffers; clear++) {
94 if (alIsBuffer(bufferlist[clear])) {
95 alDeleteBuffers(1, &bufferlist[clear]);
96 if (alGetError() != AL_NO_ERROR) {
97 printf("Error in probing OpenAL buffers.\n");
98 }
99 } else {
100 printf("Error in probing OpenAL buffers.\n");
101 }
102 }
103
104 OSI_MAX_BUFFERS = buffers;
105
106 printf("OpenAL backend info:\n Vendor: %s\n Renderer: %s\n Version: %s\n", alGetString(AL_VENDOR), alGetString(AL_RENDERER), alGetString(AL_VERSION));
107 printf(" Available sources: %d%s\n", OSI_MAX_SOURCES, (sources >= MAX_SOURCES) ? " or more" : "");
108 printf(" Available buffers: %d%s\n", OSI_MAX_BUFFERS, (buffers >= MAX_SOURCES) ? " or more" : "");
109
110 alDistanceModel ( AL_INVERSE_DISTANCE );
111 int error = alGetError();
112 if (error != AL_NO_ERROR) {
113 printf("OpenAL Error: %d alDistanceModel\n", error);
114 }
115
116 alDopplerFactor (1.0f);
117 //alSpeedOfSound (SPEED_OF_SOUND); // not defined in linux yet.
118 alDopplerVelocity (SPEED_OF_SOUND);
119 error = alGetError();
120 if (error != AL_NO_ERROR) {
121 printf("OpenAL Error: %d alDopplerX\n", error);
122 }
123
124
125 alListenerfv(AL_POSITION, far_away );
126 alListenerfv(AL_VELOCITY, zeroes );
127 alListenerfv(AL_ORIENTATION, front );
128 error = alGetError();
129 if (error != AL_NO_ERROR) {
130 printf("OpenAL Error: %d alListenerfv\n", error);
131 }
132
133 engpri = NULL;
134 global_gain = 1.0f;
135
136 // initialise mappings
137 grass.schar = &CarSoundData::grass;
139 curb.schar = &CarSoundData::curb;
140 road.schar = &CarSoundData::road;
143 turbo.schar = &CarSoundData::turbo;
144 axle.schar = &CarSoundData::axle;
145
147}
148
150{
151 delete sourcepool;
152 for (unsigned int i=0; i<sound_list.size(); i++) {
153 delete sound_list[i];
154 }
155 delete [] engpri;
156 alcDestroyContext (cc);
157 alcCloseDevice (dev);
158
159 if (car_src) {
160 delete [] car_src;
161 }
162}
163
165{
166 engpri = new SoundPri[n_cars];
167 car_src = new SoundSource[n_cars];
168}
169
170
171TorcsSound* OpenalSoundInterface::addSample (const char* filename, int flags, bool loop, bool static_pool)
172{
173 TorcsSound* sound = new OpenalTorcsSound (filename, this, flags, loop, static_pool);
174 sound_list.push_back (sound);
175 return sound;
176}
177
178void OpenalSoundInterface::update(CarSoundData** car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs, sgVec3 a_obs)
179{
180
181 ALfloat listener_pos[3];
182 //ALfloat listener_speed[3];
183 ALfloat listener_orientation[6];
184 ALfloat zeros[] = {0.0f, 0.0f, 0.0f};
185
186 int i;
187 for (i = 0; i<3; i++) {
188 listener_pos[i] = p_obs[i];
189 //listener_speed[i] = 0;// u_obs[i];
190 listener_orientation[i] = c_obs[i];
191 listener_orientation[i+3] = a_obs[i];
192 }
193
194 alListenerfv(AL_POSITION, listener_pos );
195#ifdef USE_OPENAL_DOPPLER
196 alListenerfv(AL_VELOCITY, listener_speed );
197#else
198 alListenerfv(AL_VELOCITY, zeros);
199#endif
200 alListenerfv(AL_ORIENTATION, listener_orientation );
201 alListenerf(AL_GAIN, getGlobalGain());
202
203 for (i = 0; i<n_cars; i++) {
204 car_sound_data[i]->copyEngPri(engpri[i]);
205 int id = engpri[i].id;
206 sgVec3 p;
207 sgVec3 u;
208 car_sound_data[id]->getCarPosition(p);
209 car_sound_data[id]->getCarSpeed(u);
210 car_src[id].setSource (p, u);
211 car_src[id].setListener (p_obs, u_obs);
212 car_src[id].update();
213 engpri[id].a = car_src[id].a;
214 }
215
216
217 qsort ((void*) engpri, n_cars, sizeof(SoundPri), &sortSndPriority);
218
219
220 int nsrc = MIN(sourcepool->getNbSources(), n_engine_sounds);
221
222 // Reverse order is important to gain free sources from stopped engine sounds
223 // before attempting to start new ones.
224 for (i = n_cars - 1; i >= 0; i--) {
225 int id = engpri[i].id;
226 sgVec3 p;
227 sgVec3 u;
228 CarSoundData* sound_data = car_sound_data[id];
229 sound_data->getCarPosition(p);
230 sound_data->getCarSpeed(u);
231 TorcsSound* engine = sound_data->getEngineSound();
232 engine->setSource(p, u);
233#ifdef USE_OPENAL_DOPPLER
234 engine->setPitch (sound_data->engine.f);
235#else
236 engine->setPitch (car_src[id].f*sound_data->engine.f);
237#endif
238 engine->setVolume (sound_data->engine.a * exp(sound_data->engine.lp-1.0));
239 //engine->setLPFilter(sound_data->engine.lp);
240
241 engine->update();
242 if (i < nsrc) {
243 engine->start();
244 } else {
245 engine->stop();
246 }
247 }
248
249 float max_skid_vol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
250 int max_skid_id[4] = {0,0,0,0};
251 int id;
252 for (id = 0; id<n_cars; id++) {
253 CarSoundData* sound_data = car_sound_data[id];
254 for (int j=0; j<4; j++) {
255 float skvol=sound_data->attenuation*sound_data->wheel[j].skid.a;
256 if (skvol > max_skid_vol[j]) {
257 max_skid_vol[j] = skvol;
258 max_skid_id[j] = id;
259 }
260 }
261 }
262
263 for (i = 0; i<4; i++) {
264 int id = max_skid_id[i];
265 WheelSoundData* sound_data = car_sound_data[id]->wheel;
266 skid_sound[i]->setSource (sound_data[i].p, sound_data[i].u);
267 skid_sound[i]->setVolume (sound_data[i].skid.a);
268#ifdef USE_OPENAL_DOPPLER
270 skid_sound[i]->setPitch (MIN(sound_data[i].skid.f, 1.0f));
271#else
272 float mod_f = car_src[id].f;
273 skid_sound[i]->setPitch (sound_data[i].skid.f * mod_f);
274#endif
275 skid_sound[i]->update();
276 if (sound_data[i].skid.a > VOLUME_CUTOFF) {
277 skid_sound[i]->start();
278 } else {
279 skid_sound[i]->stop();
280 }
281 }
282
283
284 // other looping sounds
285 road.snd = road_ride_sound;
288
292
296
297 curb.snd = curb_ride_sound;
300
304
308
312
313 turbo.snd = turbo_sound;
316
317 axle.snd = axle_sound;
320
321 // One-off sounds
322 for (id = 0; id<n_cars; id++) {
323 CarSoundData* sound_data = car_sound_data[id];
324 sgVec3 p;
325 sgVec3 u = {0, 0, 0};
326 if (sound_data->crash) {
328 curCrashSnd = 0;
329 }
330 sound_data->getCarPosition(p);
331 sound_data->getCarSpeed(u);
332 crash_sound[curCrashSnd]->setSource (p, u);
333 crash_sound[curCrashSnd]->setVolume (1.0f);
334 crash_sound[curCrashSnd]->setPitch (1.0f);
335 crash_sound[curCrashSnd]->update();
336 crash_sound[curCrashSnd]->start();
337 }
338
339 if (sound_data->bang) {
340 sound_data->getCarPosition(p);
341 sound_data->getCarSpeed(u);
342 bang_sound->setSource (p, u);
343 bang_sound->setVolume (1.0f);
344 bang_sound->setPitch (1.0f);
345 bang_sound->update();
346 bang_sound->start();
347 }
348
349 if (sound_data->bottom_crash) {
350 sound_data->getCarPosition(p);
351 sound_data->getCarSpeed(u);
352 bottom_crash_sound->setSource (p, u);
353 bottom_crash_sound->setVolume (1.0f);
354 bottom_crash_sound->setPitch (1.0f);
355 bottom_crash_sound->update();
356 bottom_crash_sound->start();
357 }
358
359 if (sound_data->gear_changing) {
360 sound_data->getCarPosition(p);
361 sound_data->getCarSpeed(u);
362 gear_change_sound->setSource (p, u);
363 gear_change_sound->setReferenceDistance (1.0f);
364 gear_change_sound->setVolume (1.0f);
365 gear_change_sound->setPitch (1.0f);
366 gear_change_sound->update();
367 gear_change_sound->start();
368 }
369 }
370}
371
372
374{
375 alListenerf(AL_GAIN, 0.0f);
376}
377
378
380{
381 int nbdynsources = OSI_MAX_SOURCES - n_static_sources_in_use;
382 sourcepool = new SharedSourcePool(nbdynsources);
383 printf(" #static sources: %d\n", n_static_sources_in_use);
384 printf(" #dyn sources : %d\n", sourcepool->getNbSources());
385}
386
387
389{
390 // Do we have a source left for static assigned sources?
392 alGenSources (1, source);
393 int error = alGetError();
394 if (error != AL_NO_ERROR) {
395 return false;
396 } else {
398 return true;
399 }
400 } else {
401 return false;
402 }
403}
404
406{
407 int id = smap->id;
408 float max_vol = smap->max_vol;
409 QSoundChar CarSoundData::*p2schar = smap->schar;
410 QSoundChar* schar = &(car_sound_data[id]->*p2schar);
411 TorcsSound* snd = smap->snd;
412
413 sgVec3 p;
414 sgVec3 u = {0.0f, 0.0f, 0.0f};
415
416 car_sound_data[id]->getCarPosition(p);
417#ifdef USE_OPENAL_DOPPLER
418 car_sound_data[id]->getCarSpeed(u);
419#endif
420 snd->setSource (p, u);
421 snd->setVolume (schar->a);
422#ifdef USE_OPENAL_DOPPLER
423 snd->setPitch (schar->f);
424#else
425 snd->setPitch (schar->f * car_src[id].f);
426#endif
427 snd->update();
428 if (max_vol > VOLUME_CUTOFF) {
429 snd->start();
430 } else {
431 snd->stop();
432 }
433}
struct WheelSoundData_ WheelSoundData
static Point p[4]
Definition Convex.cpp:54
struct QSoundChar_ QSoundChar
struct QueueSoundMap_ QueueSoundMap
A queue containing mappings between sounds and sound sources.
#define VOLUME_CUTOFF
int sortSndPriority(const void *a, const void *b)
struct SoundPri_ SoundPri
Sound priority, used to sort cars according to amplitude attenuation.
Manages the source sound of each individual car.
QSoundChar grass_skid
QSoundChar engine_backfire
QSoundChar grass
QSoundChar turbo
float attenuation
global distance attenuation
void getCarSpeed(sgVec3 u)
QSoundChar curb
QSoundChar engine
TorcsSound * getEngineSound()
QSoundChar drag_collision
WheelSoundData wheel[4]
QSoundChar axle
void getCarPosition(sgVec3 p)
QSoundChar road
virtual TorcsSound * addSample(const char *filename, int flags=(ACTIVE_VOLUME|ACTIVE_PITCH), bool loop=false, bool static_pool=true)
virtual void setNCars(int n_cars)
static const int OSI_MIN_DYNAMIC_SOURCES
Define this to use the OpenAL Doppler.
virtual float getGlobalGain()
OpenalSoundInterface(float sampling_rate, int n_channels)
virtual void SetMaxSoundCar(CarSoundData **car_sound_data, QueueSoundMap *smap)
virtual bool getStaticSource(ALuint *source)
SharedSourcePool * sourcepool
virtual void update(CarSoundData **car_sound_data, int n_cars, sgVec3 p_obs, sgVec3 u_obs, sgVec3 c_obs, sgVec3 a_obs)
Openal torcs sound.
Definition TorcsSound.h:158
SoundInterface(float sampling_rate, int n_channels)
Make a new sound interface.
TorcsSound * turbo_sound
turbo spinning sound
QueueSoundMap turbo
QueueSoundMap backfire_loop
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.
TorcsSound * metal_skid_sound
metal skidding on metal
TorcsSound * backfire_loop_sound
exhaust backfire sound
TorcsSound * grass_skid_sound
skidding on dirt/grass
TorcsSound * axle_sound
axle/gear spinning sound
TorcsSound * skid_sound[4]
set of skid sounds, one per tyre
QueueSoundMap metal_skid
TorcsSound * grass_ride_sound
rolling on dirt/grass
QueueSoundMap road
The following are mappings for sound prioritisation.
QueueSoundMap axle
TorcsSound * curb_ride_sound
rolling on curb
QueueSoundMap grass
float sampling_rate
sampling rate
TorcsSound * crash_sound[NB_CRASH_SOUND]
list of crash sounds
TorcsSound * road_ride_sound
rolling on normal road
int n_channels
number of channels
std::vector< TorcsSound * > sound_list
keeps track of sounds used
TorcsSound * gear_change_sound
sound when changing gears
TorcsSound * bottom_crash_sound
bang when crashing from a great height
QueueSoundMap grass_skid
int n_engine_sounds
number of simultaneous engines
QueueSoundMap curb
int curCrashSnd
holds current crash sound used - the sound cycles
SoundPri * engpri
the engine priority, used for sorting
TorcsSound * bang_sound
sounds when suspension fully compressed
Sound source management.
Definition TorcsSound.h:141
A generic TORCS sound.
Definition TorcsSound.h:53
virtual void setSource(sgVec3 p, sgVec3 u)
Definition TorcsSound.h:76
virtual void start()=0
virtual void update()=0
virtual void setPitch(float pitch)
Set the pitch.
virtual void stop()=0
virtual void setVolume(float vol)
Set the volume.
static CarSoundData ** car_sound_data
Definition grsound.cpp:38
#define NB_CRASH_SOUND
#define SPEED_OF_SOUND
float max_vol
Max.
int id
The id of the car producing the sound, used for retrieving doppler effects etc.
QSoundChar CarSoundData::* schar
The calculated sound characteristic.
TorcsSound * snd
The raw sound.
QSoundChar skid
#define MIN(x, y)
Definition tgf.h:56
#define MAX(x, y)
Definition tgf.h:52