Subversion Repositories Games.Carmageddon

Rev

Rev 18 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "3d.h"
2
#include "audio.h"
3
#include "harness/trace.h"
4
#include "resource.h"
5
#include "s3sound.h"
6
#include <math.h>
7
#include <stdio.h>
8
#include <string.h>
9
 
10
tS3_vector3 gS3_listener_position_old;
11
tS3_vector3 gS3_listener_position_now;
12
tS3_vector3 gS3_listener_vel_now;
13
tS3_vector3 gS3_listener_left_now;
14
 
15
void* gS3_listener_pos_ptr;
16
void* gS3_listener_vel_ptr;
17
void* gS3_listener_left_ptr;
18
 
19
int gS3_listener_pos_is_brender;
20
int gS3_listener_vel_is_brender;
21
int gS3_listener_left_is_brender;
22
 
23
float dword_531D9C;
24
float flt_531D7C;
25
float flt_531D98;
26
 
20 pmbaty 27
void S3Set3DSoundEnvironment(float a1, float a2, float a3) {
1 pmbaty 28
    float tmp;
29
 
20 pmbaty 30
    if (a1 == -1.0f) {
31
        a1 = 0.25f;
1 pmbaty 32
    }
33
    if (a2 == -1.0f) {
34
        a2 = 1.2f;
35
    }
36
    if (a3 == -1.0f) {
37
        a3 = 130000.0f;
38
    }
20 pmbaty 39
    dword_531D9C = a1;
1 pmbaty 40
    tmp = sqrtf(a3 / a2);
41
    flt_531D7C = tmp;
42
    flt_531D98 = tmp * dword_531D9C;
43
    gS3_listener_position_now.x = 0.0;
44
    gS3_listener_position_now.y = 0.0;
45
    gS3_listener_position_now.z = 0.0;
46
    gS3_listener_vel_now.x = 0.0;
47
    gS3_listener_vel_now.y = 0.0;
48
    gS3_listener_vel_now.z = 0.0;
49
    gS3_listener_left_now.x = 0.0;
50
    gS3_listener_left_now.y = 0.0;
51
    gS3_listener_left_now.z = 0.0;
52
}
53
 
54
void S3CopyVector3(void* a1, void* a2, int pBrender_vector) {
55
    if (pBrender_vector) {
56
        S3CopyBrVector3((tS3_vector3*)a1, (br_vector3*)a2);
57
    } else {
58
        S3CopyS3Vector3((tS3_vector3*)a1, (tS3_vector3*)a2);
59
    }
60
}
61
 
62
void S3CopyBrVector3(tS3_vector3* a1, br_vector3* a2) {
63
    a1->x = a2->v[0];
64
    a1->y = a2->v[1];
65
    a1->z = a2->v[2];
66
}
67
 
68
void S3CopyS3Vector3(tS3_vector3* a1, tS3_vector3* a2) {
69
    *a1 = *a2;
70
}
71
 
72
void S3BindListenerPositionBRender(br_vector3* pos) {
73
    gS3_listener_pos_ptr = pos;
74
    gS3_listener_pos_is_brender = 1;
75
    S3CopyBrVector3(&gS3_listener_position_old, pos);
76
}
77
 
78
void S3BindListenerVelocityBRender(br_vector3* vel) {
79
    gS3_listener_vel_ptr = vel;
80
    gS3_listener_vel_is_brender = 1;
81
}
82
 
83
void S3BindListenerLeftBRender(br_vector3* left) {
84
    gS3_listener_left_ptr = left;
85
    gS3_listener_left_is_brender = 1;
86
}
87
 
88
void S3UpdateListenerVectors(void) {
89
    if (gS3_listener_pos_ptr) {
90
        S3CopyVector3(&gS3_listener_position_now, gS3_listener_pos_ptr, gS3_listener_pos_is_brender);
91
    }
92
    if (gS3_listener_vel_ptr) {
93
        S3CopyVector3(&gS3_listener_vel_now, gS3_listener_vel_ptr, gS3_listener_vel_is_brender);
94
    } else {
95
        gS3_listener_vel_now.x = (gS3_listener_position_now.x - gS3_listener_position_old.x) / 1000.0 * gS3_service_time_delta;
96
        gS3_listener_vel_now.y = (gS3_listener_position_now.y - gS3_listener_position_old.y) / 1000.0 * gS3_service_time_delta;
97
        gS3_listener_vel_now.z = (gS3_listener_position_now.z - gS3_listener_position_old.z) / 1000.0 * gS3_service_time_delta;
98
        gS3_listener_position_old = gS3_listener_position_now;
99
    }
100
    if (gS3_listener_left_ptr) {
101
        S3CopyVector3(&gS3_listener_left_now, gS3_listener_left_ptr, gS3_listener_left_is_brender);
102
    } else {
103
        gS3_listener_left_now.x = gS3_listener_position_now.x + 1.0;
104
        gS3_listener_left_now.y = gS3_listener_position_now.y;
105
        gS3_listener_left_now.z = gS3_listener_position_now.z;
106
    }
107
}
108
 
109
void S3ServiceAmbientSoundSources(void) {
110
    tS3_sound_source* s; // [esp+Ch] [ebp-4h]
111
 
112
    for (s = gS3_sound_sources; s; s = s->next) {
113
        if (s->ambient == 0) {
114
            continue;
115
        }
116
        if (s->period > 0) {
117
            s->time_since_last_played += gS3_service_time_delta;
118
        }
119
        if (s->channel && s->channel->tag != s->tag) {
120
            S3StopChannel(s->channel);
121
            s->channel = NULL;
122
            s->tag = 0;
123
        }
124
 
125
        if (s->channel != NULL) {
126
            continue;
127
        }
128
        if (s->time_since_last_played <= s->period || !s->period || s->tag) {
129
            if ((s->ambient_repeats == 0 || s->period == 0) && s->tag == 0) {
130
                if (s->volume > 0 && S3ServiceSoundSource(s) == 0) {
131
                    s->channel = NULL;
132
                    s->tag = 0;
133
                }
134
                s->time_since_last_played = 0;
135
            }
136
        } else {
137
            if (s->volume > 0 && S3ServiceSoundSource(s) == 0) {
138
                s->channel = NULL;
139
                s->tag = 0;
140
            }
141
            s->time_since_last_played = 0;
142
        }
143
    }
144
}
145
 
146
int S3UpdateSpatialSound(tS3_channel* chan) {
147
    int close_enough_to_play; // [esp+10h] [ebp-4h]
148
 
149
    if (chan->sound_source_ptr && chan->sound_source_ptr->ambient) {
150
        close_enough_to_play = S3Calculate3D(chan, 1);
151
    } else {
152
        close_enough_to_play = S3Calculate3D(chan, 0);
153
    }
154
    if (close_enough_to_play) {
155
        S3SyncSampleVolumeAndPan(chan);
156
        S3SyncSampleRate(chan);
157
    }
158
    return close_enough_to_play;
159
}
160
 
161
int S3BindAmbientSoundToOutlet(tS3_outlet* pOutlet, int pSound, tS3_sound_source* source, float pMax_distance, int pPeriod, int pRepeats, int pVolume, int pPitch, int pSpeed) {
162
    tS3_descriptor* desc; // [esp+Ch] [ebp-4h]
163
 
164
    if (!gS3_enabled) {
165
        return 0;
166
    }
167
    if (!source) {
168
        return eS3_error_nonexistant_source;
169
    }
170
    desc = S3GetDescriptorByID(pSound);
171
    if (!desc) {
172
        return eS3_error_bad_id;
173
    }
174
    if (desc->type != eS3_ST_sample) {
175
        return 0;
176
    }
177
    if ((!desc->sound_data || (desc->flags & 2) != 0) && !S3LoadSample(pSound)) {
178
        return eS3_error_load_sound;
179
    }
180
    if (pVolume > 255) {
181
        pVolume = 255;
182
    }
183
    if (pVolume < 0) {
184
        pVolume = 128;
185
    }
186
    if (pPitch < 0) {
187
        pPitch = 0x10000;
188
    }
189
    if (pSpeed < 0) {
190
        pSpeed = 0x10000;
191
    }
192
    source->bound_outlet = pOutlet;
193
    source->sound_id = pSound;
194
    source->volume = pVolume;
195
    source->max_distance_sq = pMax_distance;
196
    source->period = pPeriod;
197
    source->pitch = pPitch;
198
    source->speed = pSpeed;
199
    source->ambient = 1;
200
 
201
    source->ambient_repeats = pRepeats < 0 ? 0 : pRepeats;
202
    source->time_since_last_played = pPeriod;
203
    source->channel = NULL;
204
    source->tag = 0;
205
    return eS3_error_none;
206
}
207
 
208
void S3UpdateSoundSource(tS3_outlet* outlet, tS3_sound_tag tag, tS3_sound_source* src, float pMax_distance_squared, int pPeriod, tS3_repeats pAmbient_repeats, tS3_volume pVolume, int pPitch, tS3_speed pSpeed) {
209
    tS3_channel* chan;    // [esp+28h] [ebp-Ch]
210
    tS3_descriptor* desc; // [esp+2Ch] [ebp-8h]
211
    int is_sample;        // [esp+30h] [ebp-4h]
212
 
213
    is_sample = 0;
214
    if (!gS3_enabled || !src) {
215
        return;
216
    }
217
    chan = src->channel;
218
    if (tag != -1 && src->sound_id != tag) {
219
        desc = S3GetDescriptorByID(tag);
220
        if (desc == NULL) {
221
            return;
222
        }
223
        if (desc->type == eS3_ST_sample) {
224
            src->sound_id = tag;
225
            if ((desc->sound_data == NULL || (desc->flags & 2) != 0) && !S3LoadSample(tag)) {
226
                return;
227
            }
228
            is_sample = 1;
229
        }
230
    }
231
    if (pSpeed != -1) {
232
        if (pSpeed < 1) {
233
            pSpeed = 0x10000;
234
        }
235
        src->speed = pSpeed;
236
    }
237
    if (pPitch != -1) {
238
        if (pPitch < 1) {
239
            pPitch = 0x10000;
240
        }
241
        src->pitch = pPitch;
242
        if (chan && chan->descriptor && chan->descriptor->type == eS3_ST_sample) {
243
            chan->initial_pitch = S3IRandomBetweenLog(chan->descriptor->min_pitch, chan->descriptor->max_pitch, ((tS3_sample*)chan->descriptor->sound_data)->rate);
244
            chan->initial_pitch *= ldexpf(src->pitch, -16);
245
            chan->initial_pitch *= ldexpf(src->speed, -16);
246
        }
247
    }
248
    if (pAmbient_repeats != -1) {
249
        src->ambient_repeats = MAX(0, pAmbient_repeats);
250
        if (chan) {
251
            chan->repetitions = src->ambient_repeats;
252
        }
253
    }
254
    if (pMax_distance_squared != -1.0f) {
255
        src->max_distance_sq = pMax_distance_squared;
256
        if (chan) {
257
            chan->pMax_distance_squared = pMax_distance_squared;
258
        }
259
    }
260
    if (pPeriod != -1) {
261
        src->period = pPeriod;
262
    }
263
    if (pVolume != -1) {
264
        if (pVolume > 255) {
265
            pVolume = 255;
266
        }
267
        if (pVolume < 0) {
268
            pVolume = 128;
269
        }
270
        if (src->volume != pVolume) {
271
            src->volume = pVolume;
272
        }
273
        if (chan) {
274
            chan->initial_volume = pVolume;
275
        }
276
    }
277
    if (chan) {
278
        if (chan->sound_source_ptr != src) {
279
            S3StopChannel(chan);
280
        }
281
        if (!pVolume || is_sample) {
282
            chan->spatial_sound = 0;
283
            chan->needs_service = 1;
284
            S3StopChannel(chan);
285
            src->channel = 0;
286
            src->tag = 0;
287
        }
288
    }
289
}
290
 
291
void S3StopSoundSource(tS3_sound_source* src) {
292
    if (!gS3_enabled) {
293
        return;
294
    }
295
    if (src) {
296
        if (src->channel && src->tag && src->channel->tag == src->tag) {
297
            src->channel->termination_reason = eS3_tr_stopped;
298
            src->channel->spatial_sound = 0;
299
            S3StopChannel(src->channel);
300
            src->channel->sound_source_ptr = NULL;
301
        }
302
        src->ambient = 0;
303
    }
304
}
305
 
306
tS3_sound_tag S3ServiceSoundSource(tS3_sound_source* src) {
307
    tS3_channel* chan;    // [esp+30h] [ebp-10h]
308
    tS3_outlet* outlet;   // [esp+34h] [ebp-Ch]
309
    tS3_descriptor* desc; // [esp+3Ch] [ebp-4h]
310
 
311
    if (!src) {
312
        return 0;
313
    }
314
    if (!gS3_enabled || !src->ambient) {
315
        src->tag = 0;
316
        src->channel = 0;
317
        return 0;
318
    }
319
    outlet = src->bound_outlet;
320
    desc = S3GetDescriptorByID(src->sound_id);
321
    if (desc == NULL) {
322
        gS3_last_error = eS3_error_bad_id;
323
        return 0;
324
    }
325
    if (desc->type) {
326
        return 0;
327
    }
328
    memset(&gS3_channel_template, 0, sizeof(gS3_channel_template));
329
    gS3_channel_template.initial_volume = src->volume;
330
    gS3_channel_template.rate = S3IRandomBetweenLog(desc->min_pitch, desc->max_pitch, ((tS3_sample*)desc->sound_data)->rate);
331
    if (src->pitch < 0) {
332
        src->pitch = 0x10000;
333
    }
334
    if (src->speed < 0) {
335
        src->speed = 0x10000;
336
    }
337
 
338
    gS3_channel_template.rate = ldexp(src->pitch, -16) * gS3_channel_template.rate;
339
    if (!outlet->independent_pitch) {
340
        gS3_channel_template.rate = ldexp(src->speed, -16) * gS3_channel_template.rate;
341
    }
342
    gS3_channel_template.initial_pitch = gS3_channel_template.rate;
343
    gS3_channel_template.sound_source_ptr = src;
344
    if (!src->velocity_ptr) {
345
        S3CopyVector3(&gS3_channel_template.lastpos, src->position_ptr, src->brender_vector);
346
    }
347
    gS3_channel_template.pMax_distance_squared = src->max_distance_sq;
348
    if (S3Calculate3D(&gS3_channel_template, 1) == 0) {
349
        src->tag = 0;
350
        src->channel = NULL;
351
        return 0;
352
    }
353
 
354
    chan = S3AllocateChannel(outlet, desc->priority * (gS3_channel_template.right_volume + gS3_channel_template.left_volume + 1));
355
    if (chan == NULL) {
356
        gS3_last_error = eS3_error_channel_alloc;
357
        src->tag = 0;
358
        src->channel = NULL;
359
        return 0;
360
    }
361
 
362
    if ((desc->sound_data && (desc->flags & 2) == 0) || S3LoadSample(src->sound_id)) {
363
        chan->left_volume = gS3_channel_template.left_volume * chan->volume_multiplier;
364
        chan->right_volume = gS3_channel_template.right_volume * chan->volume_multiplier;
365
        chan->rate = gS3_channel_template.rate;
366
        chan->position.x = gS3_channel_template.position.x;
367
        chan->position.y = gS3_channel_template.position.y;
368
        chan->position.z = gS3_channel_template.position.z;
369
        chan->velocity.x = gS3_channel_template.velocity.x;
370
        chan->velocity.y = gS3_channel_template.velocity.y;
371
        chan->velocity.z = gS3_channel_template.velocity.z;
372
        chan->lastpos.x = gS3_channel_template.lastpos.x;
373
        chan->lastpos.y = gS3_channel_template.lastpos.y;
374
        chan->lastpos.z = gS3_channel_template.lastpos.z;
375
        chan->initial_volume = gS3_channel_template.initial_volume;
376
        chan->initial_pitch = gS3_channel_template.initial_pitch;
377
        chan->pMax_distance_squared = gS3_channel_template.pMax_distance_squared;
378
        chan->spatial_sound = 2;
379
        chan->sound_source_ptr = src;
380
        chan->descriptor = desc;
381
        chan->tag = S3GenerateTag(outlet);
382
        chan->repetitions = src->ambient_repeats;
383
        chan->needs_service = 0;
384
        chan->termination_reason = 0;
385
        S3ExecuteSampleFilterFuncs(chan);
386
        if (S3PlaySample(chan)) {
387
            src->tag = chan->tag;
388
            src->channel = chan;
389
            return chan->tag;
390
        } else {
391
            chan->needs_service = 1;
392
            gS3_last_error = eS3_error_start_sound;
393
            return 0;
394
        }
395
    } else {
396
        gS3_last_error = eS3_error_load_sound;
397
        chan->needs_service = 1;
398
        return 0;
399
    }
400
}
401
 
402
tS3_sound_tag S3StartSound3D(tS3_outlet* pOutlet, tS3_sound_id pSound, tS3_vector3* pInitial_position, tS3_vector3* pInitial_velocity, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed) {
403
    tS3_channel* chan;    // [esp+30h] [ebp-Ch]
404
    tS3_descriptor* desc; // [esp+38h] [ebp-4h]
405
 
406
    if (!gS3_enabled) {
407
        return 0;
408
    }
409
    desc = S3GetDescriptorByID(pSound);
410
    if (!desc) {
411
        gS3_last_error = eS3_error_bad_id;
412
        return 0;
413
    }
414
    if (desc->type != eS3_ST_sample) {
415
        return 0;
416
    }
417
 
418
    if ((desc->sound_data == NULL || (desc->flags & 2) != 0) && S3LoadSample(pSound) == 0) {
419
        gS3_last_error = eS3_error_load_sound;
420
        return 0;
421
    }
422
    if (pVolume > 255) {
423
        pVolume = 255;
424
    }
425
    if (pVolume < 0) {
426
        pVolume = S3IRandomBetween(desc->min_volume, desc->max_volume, 128);
427
    }
428
    memset(&gS3_channel_template, 0, sizeof(gS3_channel_template));
429
    gS3_channel_template.volume_multiplier = 1.0;
430
    gS3_channel_template.sound_source_ptr = 0;
431
    gS3_channel_template.pMax_distance_squared = 150.0;
432
    gS3_channel_template.right_volume = pVolume;
433
    gS3_channel_template.left_volume = pVolume;
434
    gS3_channel_template.initial_volume = pVolume;
435
    gS3_channel_template.rate = S3IRandomBetweenLog(desc->min_pitch, desc->max_pitch, ((tS3_sample*)desc->sound_data)->rate);
436
    if (pPitch == -1) {
437
        pPitch = 0x10000;
438
    }
439
    if (pSpeed == -1) {
440
        pSpeed = 0x10000;
441
    }
442
    gS3_channel_template.rate = ldexpf(pPitch, -16) * gS3_channel_template.rate;
443
    if (!pOutlet->independent_pitch) {
444
        gS3_channel_template.rate = ldexpf(pSpeed, -16) * gS3_channel_template.rate;
445
    }
446
    gS3_channel_template.initial_pitch = gS3_channel_template.rate;
447
    gS3_channel_template.position = *pInitial_position;
448
    gS3_channel_template.velocity = *pInitial_velocity;
449
 
450
    if (S3Calculate3D(&gS3_channel_template, 0) == 0) {
451
        return 0;
452
    }
453
    chan = S3AllocateChannel(pOutlet, desc->priority * (gS3_channel_template.right_volume + gS3_channel_template.left_volume + 1));
454
    if (chan) {
455
        chan->left_volume = gS3_channel_template.left_volume * chan->volume_multiplier;
456
        chan->right_volume = gS3_channel_template.right_volume * chan->volume_multiplier;
457
        chan->rate = gS3_channel_template.rate;
458
        chan->spatial_sound = 1;
459
        chan->sound_source_ptr = 0;
460
        chan->descriptor = desc;
461
        chan->needs_service = 0;
462
        chan->termination_reason = 0;
463
        chan->position = gS3_channel_template.position;
464
        chan->lastpos = gS3_channel_template.lastpos;
465
        chan->velocity = gS3_channel_template.velocity;
466
        chan->repetitions = MAX(pRepeats, 0);
467
        chan->tag = S3GenerateTag(pOutlet);
468
        chan->initial_volume = gS3_channel_template.initial_volume;
469
        chan->initial_pitch = gS3_channel_template.initial_pitch;
470
        chan->pMax_distance_squared = gS3_channel_template.pMax_distance_squared;
471
        S3ExecuteSampleFilterFuncs(chan);
472
        if (S3PlaySample(chan) != 0) {
473
            return chan->tag;
474
        } else {
475
            chan->needs_service = 1;
476
            gS3_last_error = eS3_error_start_sound;
477
            return 0;
478
        }
479
    } else {
480
        gS3_last_error = eS3_error_channel_alloc;
481
        return 0;
482
    }
483
}
484
 
485
int S3Calculate3D(tS3_channel* chan, int pIs_ambient) {
486
    float attenuation;                  // [esp+2Ch] [ebp-1Ch]
487
    float doppler_shift;                // [esp+30h] [ebp-18h]
488
    float vol_multiplier;               // [esp+38h] [ebp-10h]
489
    tS3_sound_source* sound_source_ptr; // [esp+3Ch] [ebp-Ch]
490
    float dist_squared;                 // [esp+40h] [ebp-8h]
491
    float dist;                         // [esp+44h] [ebp-4h]
492
 
493
    sound_source_ptr = chan->sound_source_ptr;
494
    if (sound_source_ptr) {
495
        if (sound_source_ptr->position_ptr) {
496
            S3CopyVector3(&chan->position, sound_source_ptr->position_ptr, sound_source_ptr->brender_vector);
497
        }
498
        if (sound_source_ptr->velocity_ptr) {
499
            S3CopyVector3(&chan->velocity, sound_source_ptr->velocity_ptr, sound_source_ptr->brender_vector);
500
        } else {
501
            chan->velocity.x = (chan->position.x - chan->lastpos.x) / 1000.0f * gS3_service_time_delta;
502
            chan->velocity.y = (chan->position.y - chan->lastpos.y) / 1000.0f * gS3_service_time_delta;
503
            chan->velocity.z = (chan->position.z - chan->lastpos.z) / 1000.0f * gS3_service_time_delta;
504
            chan->lastpos = chan->position;
505
        }
506
    }
507
    dist_squared = (chan->position.z - gS3_listener_position_now.z) * (chan->position.z - gS3_listener_position_now.z)
508
        + (chan->position.x - gS3_listener_position_now.x) * (chan->position.x - gS3_listener_position_now.x)
509
        + (chan->position.y - gS3_listener_position_now.y) * (chan->position.y - gS3_listener_position_now.y);
510
    if (dist_squared < 0) {
511
        dist_squared = dist_squared * -1.0;
512
    }
513
 
514
    if (chan->pMax_distance_squared < dist_squared) {
515
        return 0;
516
    }
517
    if (dist_squared == 0.0f) {
518
        dist = 0.0f;
519
    } else {
520
        dist = sqrtf(dist_squared);
521
    }
522
    if (pIs_ambient) {
523
        doppler_shift = 1.0f - ((chan->position.z - gS3_listener_position_now.z) * (chan->velocity.z - gS3_listener_vel_now.z) + (chan->velocity.y - gS3_listener_vel_now.y) * (chan->position.y - gS3_listener_position_now.y) + (chan->position.x - gS3_listener_position_now.x) * (chan->velocity.x - gS3_listener_vel_now.x)) / dist / flt_531D98;
524
        if (doppler_shift > 2.0f) {
525
            doppler_shift = 2.0f;
526
        } else if (doppler_shift < 0.5f) {
527
            doppler_shift = 0.5;
528
        }
529
        chan->rate = chan->initial_pitch * doppler_shift;
530
    } else {
531
        chan->rate = chan->initial_pitch;
532
    }
533
 
534
    vol_multiplier = 1.0f / (dist / 6.0f + 1.0f);
535
    if (!gS3_inside_cockpit) {
536
        vol_multiplier = vol_multiplier * 1.3f;
537
    }
538
    attenuation = (chan->position.z - gS3_listener_position_now.z) * gS3_listener_left_now.z
539
        + (chan->position.y - gS3_listener_position_now.y) * gS3_listener_left_now.y
540
        + (chan->position.x - gS3_listener_position_now.x) * gS3_listener_left_now.x;
541
    if (attenuation < -1.0f) {
542
        attenuation -= ceil(attenuation);
543
    }
544
    if (attenuation > 1.0f) {
545
        attenuation -= floor(attenuation);
546
    }
547
    chan->left_volume = (attenuation + 1.0f) / 2.0f * ((double)chan->initial_volume * vol_multiplier) * chan->volume_multiplier;
548
    if (chan->left_volume < 0) {
549
        chan->left_volume = 0;
550
    }
551
    chan->right_volume = (1.0f - attenuation) / 2.0f * ((double)chan->initial_volume * vol_multiplier) * chan->volume_multiplier;
552
    if (chan->right_volume < 0) {
553
        chan->right_volume = 0;
554
    }
555
    if (chan->left_volume > 255) {
556
        chan->left_volume = 255;
557
    }
558
    if (chan->right_volume > 255) {
559
        chan->right_volume = 255;
560
    }
561
    return 1;
562
}