Skip to content

Commit d7b7fa6

Browse files
authored
Merge pull request #723 from ceski-1/fade
Add sound clicking fix from Woof
2 parents d2314a2 + fb5e19b commit d7b7fa6

File tree

8 files changed

+152
-37
lines changed

8 files changed

+152
-37
lines changed

prboom2/src/SDL/i_sound.c

Lines changed: 125 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
//e6y
7272
#include "e6y.h"
7373

74+
#include "dsda/ambient.h"
7475
#include "dsda/settings.h"
7576

7677
static dboolean registered_non_rw = false;
@@ -195,7 +196,7 @@ static Uint8 *ConvertAudioFormat(void **data, SDL_AudioSpec *sample, Uint32 *len
195196
typedef struct snd_data_s
196197
{
197198
int sfxid;
198-
const unsigned char *data;
199+
unsigned char *data;
199200
int samplelen;
200201
int samplerate;
201202
struct snd_data_s *next;
@@ -264,15 +265,85 @@ static snd_data_t *GetSndData(int sfxid, const unsigned char *data, size_t len)
264265
return target;
265266
}
266267

268+
#define FADETIME 1000 // microseconds
269+
270+
static void FadeInOutMono16(short *data, int len, int rate)
271+
{
272+
const int fadelen = rate * FADETIME / 1000000;
273+
int i;
274+
275+
if (len < fadelen)
276+
return;
277+
278+
if (data[0] != 0)
279+
{
280+
for (i = 0; i < fadelen; i++)
281+
{
282+
data[i] = data[i] * i / fadelen;
283+
}
284+
}
285+
286+
if (data[len - 1] != 0)
287+
{
288+
for (i = 0; i < fadelen; i++)
289+
{
290+
data[len - 1 - i] = data[len - 1 - i] * i / fadelen;
291+
}
292+
}
293+
}
294+
295+
static void FadeInOutMono8(byte *data, int len, int rate)
296+
{
297+
const int fadelen = rate * FADETIME / 1000000;
298+
int i;
299+
300+
if (len < fadelen)
301+
return;
302+
303+
if (data[0] != 128)
304+
{
305+
for (i = 0; i < fadelen; i++)
306+
{
307+
data[i] = (data[i] - 128) * i / fadelen + 128;
308+
}
309+
}
310+
311+
if (data[len - 1] != 128)
312+
{
313+
for (i = 0; i < fadelen; i++)
314+
{
315+
data[len - 1 - i] = (data[len - 1 - i] - 128) * i / fadelen + 128;
316+
}
317+
}
318+
}
319+
267320
#define DMXHDRSIZE 8
268321
#define DMXPADSIZE 16
269322

323+
INLINE static int GetDMXSampleRate(const byte *data)
324+
{
325+
return ((data[3] << 8) | data[2]);
326+
}
327+
328+
INLINE static dboolean IsValidDMXSound(int dmx_len, int len)
329+
{
330+
// Don't play DMX format sound lumps that think they're longer than they
331+
// really are, only contain padding, or are shorter than the padding size.
332+
return (dmx_len <= len - DMXHDRSIZE && dmx_len > DMXPADSIZE * 2);
333+
}
334+
335+
INLINE static int GetDMXLength(const byte *data)
336+
{
337+
// Read the encoded number of samples. This value includes padding.
338+
return ((data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]);
339+
}
340+
270341
INLINE static dboolean IsDMXSound(const byte *data, int len)
271342
{
272343
return len > DMXHDRSIZE && data[0] == 0x03 && data[1] == 0x00;
273344
}
274345

275-
static void CacheSounds(void)
346+
void I_CacheSounds(void)
276347
{
277348
int id;
278349
for (id = 1; id < num_sfx; id++)
@@ -283,8 +354,29 @@ static void CacheSounds(void)
283354
const byte *data = W_LumpByNum(lump);
284355
int len = W_LumpLength(lump);
285356

286-
if (!IsDMXSound(data, len))
287-
GetSndData(id, data, len);
357+
if (IsDMXSound(data, len))
358+
{
359+
int dmx_len = GetDMXLength(data);
360+
361+
if (IsValidDMXSound(dmx_len, len) && !dsda_IsLoopingAmbientSFX(id))
362+
{
363+
const int dmx_rate = GetDMXSampleRate(data);
364+
byte *dmx_data = W_GetModifiableLumpData(lump);
365+
dmx_data = &dmx_data[DMXHDRSIZE + DMXPADSIZE];
366+
dmx_len -= DMXPADSIZE * 2;
367+
FadeInOutMono8(dmx_data, dmx_len, dmx_rate);
368+
}
369+
}
370+
else
371+
{
372+
snd_data_t *snd_data = GetSndData(id, data, len);
373+
374+
if (snd_data && !dsda_IsLoopingAmbientSFX(id))
375+
{
376+
len = snd_data->samplelen / sizeof(short);
377+
FadeInOutMono16((short *)snd_data->data, len, snd_data->samplerate);
378+
}
379+
}
288380
}
289381
}
290382
}
@@ -297,32 +389,16 @@ static void CacheSounds(void)
297389
// Returns a handle.
298390
//
299391

300-
static int addsfx(int sfxid, int channel, const unsigned char *data, size_t len,
301-
const snd_data_t *snd_data)
392+
static int addsfx(int sfxid, int channel, const channel_info_t *cinfo)
302393
{
303394
channel_info_t *ci = channelinfo + channel;
304395

305396
stopchan(channel);
306397

307-
if (snd_data)
308-
{
309-
ci->data = snd_data->data;
310-
ci->enddata = ci->data + snd_data->samplelen - 1;
311-
ci->samplerate = snd_data->samplerate;
312-
ci->bits = 16;
313-
}
314-
else
315-
{
316-
ci->data = data;
317-
/* Set pointer to end of raw data. */
318-
ci->enddata = ci->data + len - 1;
319-
ci->samplerate = (ci->data[3] << 8) + ci->data[2];
320-
// Skip header and padding before samples.
321-
ci->data += DMXHDRSIZE + DMXPADSIZE;
322-
// Skip padding after samples.
323-
ci->enddata -= DMXPADSIZE;
324-
ci->bits = 8;
325-
}
398+
ci->data = cinfo->data;
399+
ci->enddata = cinfo->enddata;
400+
ci->samplerate = cinfo->samplerate;
401+
ci->bits = cinfo->bits;
326402

327403
ci->stepremainder = 0;
328404
// Should be gametic, I presume.
@@ -501,6 +577,7 @@ int I_StartSound(int id, int channel, sfx_params_t *params)
501577
int lump;
502578
size_t len;
503579
snd_data_t *snd_data = NULL;
580+
channel_info_t cinfo = {0};
504581

505582
if ((channel < 0) || (channel >= MAX_CHANNELS))
506583
#ifdef RANGECHECK
@@ -527,26 +604,41 @@ int I_StartSound(int id, int channel, sfx_params_t *params)
527604

528605
if (IsDMXSound(data, len))
529606
{
530-
// Read the encoded number of samples. This value includes padding.
531-
const int num_samples =
532-
(data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4];
607+
const int dmx_len = GetDMXLength(data);
533608

534-
// Don't play DMX format sound lumps that think they're longer than they
535-
// really are, only contain padding, or are shorter than the padding size.
536-
if (num_samples > len - DMXHDRSIZE || num_samples <= DMXPADSIZE * 2)
609+
if (IsValidDMXSound(dmx_len, len))
610+
{
611+
cinfo.data = &data[DMXHDRSIZE + DMXPADSIZE];
612+
cinfo.enddata = &cinfo.data[dmx_len - DMXPADSIZE * 2 - 1];
613+
cinfo.samplerate = GetDMXSampleRate(data);
614+
cinfo.bits = 8;
615+
}
616+
else
617+
{
537618
return -1;
619+
}
538620
}
539621
else
540622
{
541623
snd_data = GetSndData(id, data, len);
542-
if (!snd_data)
624+
625+
if (snd_data)
626+
{
627+
cinfo.data = snd_data->data;
628+
cinfo.enddata = &cinfo.data[snd_data->samplelen - 1];
629+
cinfo.samplerate = snd_data->samplerate;
630+
cinfo.bits = 16;
631+
}
632+
else
633+
{
543634
return -1;
635+
}
544636
}
545637

546638
SDL_LockMutex (sfxmutex);
547639

548640
// Returns a handle (not used).
549-
addsfx(id, channel, data, len, snd_data);
641+
addsfx(id, channel, &cinfo);
550642
updateSoundParams(channel, params);
551643

552644
SDL_UnlockMutex (sfxmutex);
@@ -825,10 +917,6 @@ void I_InitSound(void)
825917
if (!nomusicparm)
826918
I_InitMusic();
827919

828-
lprintf(LO_DEBUG, " Precaching all sound effects... ");
829-
CacheSounds();
830-
lprintf(LO_DEBUG, "done\n");
831-
832920
lprintf(LO_DEBUG, "I_InitSound: sound module ready\n");
833921
SDL_PauseAudio(0);
834922
}

prboom2/src/dsda/ambient.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ typedef struct {
4343
std::unordered_map<std::string, named_sfx_t> name_to_sfx;
4444
std::unordered_map<int, ambient_sfx_t> id_to_ambient_sfx;
4545

46+
dboolean dsda_IsLoopingAmbientSFX(int sfx_id) {
47+
for (auto &amb_sfx : id_to_ambient_sfx) {
48+
if (amb_sfx.second.sfx_id == sfx_id && amb_sfx.second.min_tics < 0)
49+
return true;
50+
}
51+
52+
return false;
53+
}
54+
4655
static ambient_sfx_t* dsda_AmbientSFX(int id) {
4756
return id_to_ambient_sfx[id].sfx_id ? &id_to_ambient_sfx[id] : NULL;
4857
}

prboom2/src/dsda/ambient.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct {
4040
int wait_tics;
4141
} ambient_source_t;
4242

43+
dboolean dsda_IsLoopingAmbientSFX(int sfx_id);
4344
void dsda_UpdateAmbientSource(ambient_source_t* source);
4445
void dsda_SpawnAmbientSource(mobj_t* mobj);
4546
void dsda_LoadAmbientSndInfo(void);

prboom2/src/i_sound.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ void I_ShutdownSound(void);
5656
// SFX I/O
5757
//
5858

59+
void I_CacheSounds(void);
60+
5961
// Initialize channels?
6062
void I_SetChannels(void);
6163

prboom2/src/s_sound.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ void S_Init(void)
203203

204204
dsda_CacheSoundLumps();
205205

206+
lprintf(LO_DEBUG, " Precaching all sound effects... ");
207+
I_CacheSounds();
208+
lprintf(LO_DEBUG, "done\n");
209+
206210
// {
207211
// int i;
208212
// const int snd_curve_length = 1200;

prboom2/src/w_memcache.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,8 @@ const void *W_LockLumpNum(int lump)
8888
{
8989
return W_LumpByNum(lump);
9090
}
91+
92+
void *W_GetModifiableLumpData(int lump)
93+
{
94+
return lump_data[lump];
95+
}

prboom2/src/w_mmap.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,8 @@ const void* W_LockLumpNum(int lump)
260260

261261
return lump_data[lump];
262262
}
263+
264+
void *W_GetModifiableLumpData(int lump)
265+
{
266+
return lump_data[lump];
267+
}

prboom2/src/w_wad.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ char* W_ReadLumpToString (int lump);
164164
const void* W_SafeLumpByNum (int lump);
165165
const void* W_LumpByNum (int lump);
166166
const void* W_LockLumpNum(int lump);
167+
void *W_GetModifiableLumpData(int lump);
167168

168169
int W_LumpNumExists(int lump);
169170
int W_LumpNameExists(const char *name);

0 commit comments

Comments
 (0)