diff --git a/src/mixer.cpp b/src/mixer.cpp index 10a9ac8933..3b30f3d25d 100644 --- a/src/mixer.cpp +++ b/src/mixer.cpp @@ -63,13 +63,17 @@ static int RateConversion(T *b, int frac_pos) return ((b[0] * ((1 << 16) - frac_pos)) + (b[1] * frac_pos)) >> 16; } +template static void mix_int16(MixerChannel *sc, int16_t *buffer, uint samples, uint8_t effect_vol) { + /* Shift required to get sample value into range for the data type. */ + const uint SHIFT = sizeof(T) * CHAR_BIT; + if (samples > sc->samples_left) samples = sc->samples_left; sc->samples_left -= samples; assert(samples > 0); - const int16_t *b = (const int16_t *)sc->memory + sc->pos; + const T *b = (const T *)sc->memory + sc->pos; uint32_t frac_pos = sc->frac_pos; uint32_t frac_speed = sc->frac_speed; int volume_left = sc->volume_left * effect_vol / 255; @@ -78,16 +82,16 @@ static void mix_int16(MixerChannel *sc, int16_t *buffer, uint samples, uint8_t e if (frac_speed == 0x10000) { /* Special case when frac_speed is 0x10000 */ do { - buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 16), -MAX_VOLUME, MAX_VOLUME); - buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 16), -MAX_VOLUME, MAX_VOLUME); + buffer[0] = Clamp(buffer[0] + (*b * volume_left >> SHIFT), -MAX_VOLUME, MAX_VOLUME); + buffer[1] = Clamp(buffer[1] + (*b * volume_right >> SHIFT), -MAX_VOLUME, MAX_VOLUME); b++; buffer += 2; } while (--samples > 0); } else { do { int data = RateConversion(b, frac_pos); - buffer[0] = Clamp(buffer[0] + (data * volume_left >> 16), -MAX_VOLUME, MAX_VOLUME); - buffer[1] = Clamp(buffer[1] + (data * volume_right >> 16), -MAX_VOLUME, MAX_VOLUME); + buffer[0] = Clamp(buffer[0] + (data * volume_left >> SHIFT), -MAX_VOLUME, MAX_VOLUME); + buffer[1] = Clamp(buffer[1] + (data * volume_right >> SHIFT), -MAX_VOLUME, MAX_VOLUME); buffer += 2; frac_pos += frac_speed; b += frac_pos >> 16; @@ -96,43 +100,7 @@ static void mix_int16(MixerChannel *sc, int16_t *buffer, uint samples, uint8_t e } sc->frac_pos = frac_pos; - sc->pos = b - (const int16_t *)sc->memory; -} - -static void mix_int8_to_int16(MixerChannel *sc, int16_t *buffer, uint samples, uint8_t effect_vol) -{ - if (samples > sc->samples_left) samples = sc->samples_left; - sc->samples_left -= samples; - assert(samples > 0); - - const int8_t *b = sc->memory + sc->pos; - uint32_t frac_pos = sc->frac_pos; - uint32_t frac_speed = sc->frac_speed; - int volume_left = sc->volume_left * effect_vol / 255; - int volume_right = sc->volume_right * effect_vol / 255; - - if (frac_speed == 0x10000) { - /* Special case when frac_speed is 0x10000 */ - do { - buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 8), -MAX_VOLUME, MAX_VOLUME); - buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 8), -MAX_VOLUME, MAX_VOLUME); - b++; - buffer += 2; - } while (--samples > 0); - } else { - do { - int data = RateConversion(b, frac_pos); - buffer[0] = Clamp(buffer[0] + (data * volume_left >> 8), -MAX_VOLUME, MAX_VOLUME); - buffer[1] = Clamp(buffer[1] + (data * volume_right >> 8), -MAX_VOLUME, MAX_VOLUME); - buffer += 2; - frac_pos += frac_speed; - b += frac_pos >> 16; - frac_pos &= 0xffff; - } while (--samples > 0); - } - - sc->frac_pos = frac_pos; - sc->pos = b - sc->memory; + sc->pos = b - (const T *)sc->memory; } static void MxCloseChannel(uint8_t channel_index) @@ -172,9 +140,9 @@ void MxMixSamples(void *buffer, uint samples) for (uint8_t idx : SetBitIterator(active)) { MixerChannel *mc = &_channels[idx]; if (mc->is16bit) { - mix_int16(mc, (int16_t*)buffer, samples, effect_vol); + mix_int16(mc, (int16_t*)buffer, samples, effect_vol); } else { - mix_int8_to_int16(mc, (int16_t*)buffer, samples, effect_vol); + mix_int16(mc, (int16_t*)buffer, samples, effect_vol); } if (mc->samples_left == 0) MxCloseChannel(idx); }