Files
@ r7643:9ec38df7caf3
Branch filter:
Location: cpp/openttd-patchpack/source/src/mixer.cpp
r7643:9ec38df7caf3
2.6 KiB
text/x-c
(svn r11174) -Codechange: add possibility to show the bounding boxes of sprites using CTRL-B so one can get a better understanding of the used bounding boxes to fix the glitches that still exist. Patch by frosch.
Note that this is not completely glitch free, bounding boxes sometimes aren't removed properly. This is due to the fact that the bounding boxes sometimes are larger than the sprite, which causes a smaller part than the bounding box to be redrawn. This is NOT a bug, but a known implementation limit as we do not want to slow down normal games so the debug graphics are always 100% correct.
Note that this is not completely glitch free, bounding boxes sometimes aren't removed properly. This is due to the fact that the bounding boxes sometimes are larger than the sprite, which causes a smaller part than the bounding box to be redrawn. This is NOT a bug, but a known implementation limit as we do not want to slow down normal games so the debug graphics are always 100% correct.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | /* $Id$ */
/** @file mixer.cpp*/
#include "stdafx.h"
#include "openttd.h"
#include "mixer.h"
struct MixerChannel {
bool active;
/* pointer to allocated buffer memory */
int8 *memory;
/* current position in memory */
uint32 pos;
uint32 frac_pos;
uint32 frac_speed;
uint32 samples_left;
/* Mixing volume */
uint volume_left;
uint volume_right;
uint flags;
};
static MixerChannel _channels[8];
static uint32 _play_rate;
static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples)
{
int8 *b;
uint32 frac_pos;
uint32 frac_speed;
uint volume_left;
uint volume_right;
if (samples > sc->samples_left) samples = sc->samples_left;
sc->samples_left -= samples;
assert(samples > 0);
b = sc->memory + sc->pos;
frac_pos = sc->frac_pos;
frac_speed = sc->frac_speed;
volume_left = sc->volume_left;
volume_right = sc->volume_right;
if (frac_speed == 0x10000) {
/* Special case when frac_speed is 0x10000 */
do {
buffer[0] += *b * volume_left >> 8;
buffer[1] += *b * volume_right >> 8;
b++;
buffer += 2;
} while (--samples > 0);
} else {
do {
buffer[0] += *b * volume_left >> 8;
buffer[1] += *b * volume_right >> 8;
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;
}
static void MxCloseChannel(MixerChannel *mc)
{
if (mc->flags & MX_AUTOFREE) free(mc->memory);
mc->active = false;
mc->memory = NULL;
}
void MxMixSamples(void *buffer, uint samples)
{
MixerChannel *mc;
/* Clear the buffer */
memset(buffer, 0, sizeof(int16) * 2 * samples);
/* Mix each channel */
for (mc = _channels; mc != endof(_channels); mc++) {
if (mc->active) {
mix_int8_to_int16(mc, (int16*)buffer, samples);
if (mc->samples_left == 0) MxCloseChannel(mc);
}
}
}
MixerChannel *MxAllocateChannel()
{
MixerChannel *mc;
for (mc = _channels; mc != endof(_channels); mc++)
if (mc->memory == NULL) {
mc->active = false;
return mc;
}
return NULL;
}
void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, uint size, uint rate, uint flags)
{
mc->memory = mem;
mc->flags = flags;
mc->frac_pos = 0;
mc->pos = 0;
mc->frac_speed = (rate << 16) / _play_rate;
/* adjust the magnitude to prevent overflow */
while (size & 0xFFFF0000) {
size >>= 1;
rate = (rate >> 1) + 1;
}
mc->samples_left = size * _play_rate / rate;
}
void MxSetChannelVolume(MixerChannel *mc, uint left, uint right)
{
mc->volume_left = left;
mc->volume_right = right;
}
void MxActivateChannel(MixerChannel* mc)
{
mc->active = true;
}
bool MxInitialize(uint rate)
{
_play_rate = rate;
return true;
}
|