Skip to content

Commit 95f4f98

Browse files
committed
SOUNDS: Fix playback of looping sounds
Adds back some custom parsing of wav chunks, but minimal Reported by lurq Broken since alpha6-ish
1 parent 42246d2 commit 95f4f98

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

release-notes-latest.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Leaving these here as bugs between dev versions of 3.6 aren't in the release not
3232
- Will now check PAKx.PAK if pakx.pak not present (fixes #637, reported by nzmyers)
3333
- Skyboxes rotated to match other quake engines (part of #629, requested by inf1niti & lurq)
3434
- Skyboxes will be loaded on map start if specified in worldspawn (fixes #629, requested by inf1niti & lurq)
35+
- Fixed playback of looping sounds when using libsndfile to load sounds (reported by lurq)
3536

3637
### Changes from alpha8=>alpha9 (July 13th => November 14th, 2021)
3738

snd_mem.c

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,64 @@ sf_count_t SFVIO_Tell(void *user_data)
666666
return sfviodata->position;
667667
}
668668

669+
static qbool S_ParseCueMark(const byte* chunk, int len, int cue_point_id, int* sample_length)
670+
{
671+
int pos = 0;
672+
673+
*sample_length = 0;
674+
while (pos < len - 8) {
675+
unsigned int size = BuffLittleLong(chunk + pos + 4);
676+
677+
// Looking for ltxt chunk with purpose "mark"
678+
if (size >= 20 && !strncmp(chunk + pos, "ltxt", 4) && !strncmp(chunk + pos + 16, "mark", 4)) {
679+
// Might be for a different cue point
680+
if (cue_point_id == BuffLittleLong(chunk + pos + 8)) {
681+
*sample_length = BuffLittleLong(chunk + pos + 12);
682+
return true;
683+
}
684+
}
685+
686+
pos += size;
687+
}
688+
689+
return false;
690+
}
691+
692+
static qbool S_FindCuePointSampleLength(SNDFILE* sndfile, int cue_point_id, int* sample_length)
693+
{
694+
SF_CHUNK_INFO chunk_info;
695+
chunk_info.datalen = 0;
696+
strlcpy(chunk_info.id, "LIST", sizeof(chunk_info.id));
697+
chunk_info.id_size = 4;
698+
SF_CHUNK_ITERATOR* iterator = sf_get_chunk_iterator(sndfile, &chunk_info);
699+
byte chunk_data[1024];
700+
701+
*sample_length = 0;
702+
703+
while (iterator != NULL) {
704+
if (sf_get_chunk_size(iterator, &chunk_info) != SF_ERR_NO_ERROR) {
705+
break;
706+
}
707+
708+
if (chunk_info.datalen >= 24 && chunk_info.datalen <= sizeof(chunk_data)) {
709+
chunk_info.data = chunk_data;
710+
711+
if (sf_get_chunk_data(iterator, &chunk_info) != SF_ERR_NO_ERROR) {
712+
break;
713+
}
714+
else if (chunk_data[0] == 'a' && chunk_data[1] == 'd' && chunk_data[2] == 't' && chunk_data[3] == 'l') {
715+
if (S_ParseCueMark(chunk_data + 4, chunk_info.datalen - 4, cue_point_id, sample_length)) {
716+
return true;
717+
}
718+
}
719+
}
720+
721+
iterator = sf_next_chunk_iterator(iterator);
722+
}
723+
724+
return false;
725+
}
726+
669727
sfxcache_t *S_LoadSound (sfx_t *s)
670728
{
671729
char namebuffer[256];
@@ -711,13 +769,23 @@ sfxcache_t *S_LoadSound (sfx_t *s)
711769
buf = (short *)Q_malloc(sfinfo.frames * sfinfo.channels * sizeof(short));
712770
sf_readf_short(sndfile, buf, sfinfo.frames);
713771
cue_count = 0;
714-
sf_command(sndfile, SFC_GET_CUE_COUNT, &cue_count, sizeof(cue_count));
772+
sf_command(sndfile, SFC_GET_CUE_COUNT, &cue_count, sizeof(cue_count));
715773
loopstart = -1;
716-
if (cue_count != 0)
717-
{
718-
sf_command(sndfile, SFC_GET_CUE, &sfcues, sizeof(sfcues)) ;
719-
loopstart = sfcues.cue_points[0].position;
774+
775+
if (cue_count != 0) {
776+
int loop_sample_count;
777+
778+
sf_command(sndfile, SFC_GET_CUE, &sfcues, sizeof(sfcues)) ;
779+
780+
if (S_FindCuePointSampleLength(sndfile, sfcues.cue_points[0].position, &loop_sample_count)) {
781+
loopstart = sfcues.cue_points[0].sample_offset;
782+
if (loopstart + loop_sample_count > sfinfo.frames) {
783+
Sys_Error("Sound %s has a bad loop length", s->name);
784+
}
785+
sfinfo.frames = loopstart + loop_sample_count;
786+
}
720787
}
788+
721789
sf_close(sndfile);
722790

723791
if (sfinfo.channels < 1 || sfinfo.channels > 2) {

0 commit comments

Comments
 (0)