[audio] Handle multiple cue points in wav files

Sounds in Arcane Dimensions (at least those used by ad_tears) specify
start and end cue points. The code was using only the final point in the
list and thus breaking looped sounds. Now, the first cue point is used
as the loop start, and the second (if present), the sample length. Both
are bounds-checked against the wav's sample count. Fixes sound locking
up during the first seconds in ad_tears.
This commit is contained in:
Bill Currie 2022-05-21 15:44:34 +09:00
parent 5cfbafc176
commit e967724196

View file

@ -181,14 +181,13 @@ wav_get_info (QFile *file)
riff_data_t *data = 0; riff_data_t *data = 0;
riff_cue_t *cue; riff_cue_t *cue;
riff_d_cue_t *dcue; riff_d_cue_t *dcue = 0;
riff_d_cue_point_t *cp = 0;
riff_list_t *list; riff_list_t *list;
riff_d_chunk_t **lck; riff_d_chunk_t **lck;
riff_ltxt_t *ltxt; //riff_ltxt_t *ltxt;
riff_d_ltxt_t *dltxt = 0; //riff_d_ltxt_t *dltxt = 0;
wavinfo_t info; wavinfo_t info;
@ -211,8 +210,6 @@ wav_get_info (QFile *file)
case RIFF_CASE ('c','u','e',' '): case RIFF_CASE ('c','u','e',' '):
cue = (riff_cue_t *) *ck; cue = (riff_cue_t *) *ck;
dcue = cue->cue; dcue = cue->cue;
if (dcue->count)
cp = &dcue->cue_points[dcue->count - 1];
break; break;
case RIFF_CASE ('L','I','S','T'): case RIFF_CASE ('L','I','S','T'):
list = (riff_list_t *) *ck; list = (riff_list_t *) *ck;
@ -221,8 +218,8 @@ wav_get_info (QFile *file)
for (lck = list->chunks; *lck; lck++) { for (lck = list->chunks; *lck; lck++) {
RIFF_SWITCH ((*lck)->name) { RIFF_SWITCH ((*lck)->name) {
case RIFF_CASE ('l','t','x','t'): case RIFF_CASE ('l','t','x','t'):
ltxt = (riff_ltxt_t *) *lck; //ltxt = (riff_ltxt_t *) *lck;
dltxt = &ltxt->ltxt; //dltxt = &ltxt->ltxt;
break; break;
} }
} }
@ -252,15 +249,19 @@ wav_get_info (QFile *file)
info.width = dfmt->bits_per_sample / 8; info.width = dfmt->bits_per_sample / 8;
info.channels = dfmt->channels; info.channels = dfmt->channels;
info.frames = 0; info.frames = 0;
if (cp) { info.frames = data->ck.len / (info.width * info.channels);
info.loopstart = cp->sample_offset; if (dcue && dcue->count) {
if (dltxt) if (dcue->cue_points[0].sample_offset < info.frames) {
info.frames = info.loopstart + dltxt->len; info.loopstart = dcue->cue_points[0].sample_offset;
}
if (dcue->count > 1) {
info.frames = min (info.frames, dcue->cue_points[1].sample_offset);
}
//if (dltxt)
// info.frames = info.loopstart + dltxt->len;
} else { } else {
info.loopstart = -1; info.loopstart = -1;
} }
if (!info.frames)
info.frames = data->ck.len / (info.width * info.channels);
info.dataofs = *(int *)data->data; info.dataofs = *(int *)data->data;
info.datalen = data->ck.len; info.datalen = data->ck.len;