diff --git a/Quake/snd_mem.c b/Quake/snd_mem.c index fc4b9ba4..380be115 100644 --- a/Quake/snd_mem.c +++ b/Quake/snd_mem.c @@ -114,14 +114,12 @@ static void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) } // box filter - // FIXME: doesn't handle the start or end of the sound properly // box_half_width is the number of samples on each side of a given sample // that are averaged together. - // for the most common case, 11025Hz => 44100Hz, i.e. stepscale = 0.25, - // I determined that a box width of 5 (i.e. a box_half_width of 2) produces - // the best sounding results. - const int box_half_width = CLAMP(0, (1 / (stepscale * 2)), 8); + // for 44100Hz output, a box width of 5 (i.e. a box_half_width of 2) seems + // to sound the best + const int box_half_width = CLAMP(0, sc->speed / 22050, 4); if (box_half_width > 0) { @@ -129,26 +127,31 @@ static void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) int history[box_half_width]; memset(history, 0, sizeof(history)); int box_sum = 0; - for (i = 0; i < outcount; i++) + for (i = 0; i < (outcount + box_half_width); i++) { - const int sample_at_i = getsample(sc->data, sc->width, i); - + // calculate the new sample we will write + const int sample_at_i = getsample(sc->data, sc->width, CLAMP(0, i, outcount - 1)); box_sum += sample_at_i; box_sum -= history[0]; - const int newsample = box_sum / box_width; - const int write_loc = CLAMP(0, i - box_half_width, outcount - 1); - - // before writing the sample at write_loc, copy it to the end of the history buffer + // shift the entries in the history buffer left, discarding the entry + // at history[0] and leaving a space at history[box_half_width-1] int j; for (j=0; j<(box_half_width-1); j++) { history[j] = history[j+1]; } - history[box_half_width-1] = getsample(sc->data, sc->width, write_loc); - putsample(sc->data, sc->width, write_loc, newsample); + // save the sample we are going to overwrite at history[box_half_width-1] + const int write_loc = i - box_half_width; + history[box_half_width-1] = getsample(sc->data, sc->width, CLAMP(0, write_loc, outcount - 1)); + + // only write the new sample if it lies within the bounds of the output array + if (write_loc >= 0 && write_loc < outcount) + { + putsample(sc->data, sc->width, write_loc, newsample); + } } } }