src/flac/decode.c : Fix a cast-align warning from GCC.

The old code was creating an array of FLAC__int8, and then casting
that to a set of signed and unsigned 16 and 32 bit integers. This
was replaced with a single union containing all the requred array.

This solution means that there are fewer pointer casts and actually
gives the compiler more information with which to generate fast code.
This commit is contained in:
Erik de Castro Lopo
2014-06-27 21:58:26 +10:00
parent 1f7c085960
commit 40e817dc52

View File

@@ -966,12 +966,16 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
));
unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel;
unsigned frame_bytes = 0;
static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
FLAC__uint8 *u8buffer = (FLAC__uint8 *)s8buffer;
FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer;
FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer;
FLAC__int32 *s32buffer = (FLAC__int32 *)s8buffer;
FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer;
static union
{ FLAC__int8 s8buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
FLAC__uint8 u8buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)];
FLAC__int16 s16buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int16)];
FLAC__uint16 u16buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int16)];
FLAC__int32 s32buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS];
FLAC__uint32 u32buffer [FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS];
} ubuf;
size_t bytes_to_write = 0;
(void)decoder;
@@ -1092,7 +1096,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
}
if(decoder_session->replaygain.apply) {
bytes_to_write = FLAC__replaygain_synthesis__apply_gain(
u8buffer,
ubuf.u8buffer,
!is_big_endian,
is_unsigned_samples,
buffer,
@@ -1108,17 +1112,17 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
}
/* first some special code for common cases */
else if(is_big_endian == is_big_endian_host_ && !is_unsigned_samples && channels == 2 && bps+shift == 16) {
FLAC__int16 *buf1_ = s16buffer + 1;
FLAC__int16 *buf1_ = ubuf.s16buffer + 1;
if(is_big_endian)
memcpy(s16buffer, ((FLAC__byte*)(buffer[0]))+2, sizeof(FLAC__int32) * wide_samples - 2);
memcpy(ubuf.s16buffer, ((FLAC__byte*)(buffer[0]))+2, sizeof(FLAC__int32) * wide_samples - 2);
else
memcpy(s16buffer, buffer[0], sizeof(FLAC__int32) * wide_samples);
memcpy(ubuf.s16buffer, buffer[0], sizeof(FLAC__int32) * wide_samples);
for(sample = 0; sample < wide_samples; sample++, buf1_+=2)
*buf1_ = (FLAC__int16)buffer[1][sample];
bytes_to_write = 4 * sample;
}
else if(is_big_endian == is_big_endian_host_ && !is_unsigned_samples && channels == 1 && bps+shift == 16) {
FLAC__int16 *buf1_ = s16buffer;
FLAC__int16 *buf1_ = ubuf.s16buffer;
for(sample = 0; sample < wide_samples; sample++)
*buf1_++ = (FLAC__int16)buffer[0][sample];
bytes_to_write = 2 * sample;
@@ -1128,35 +1132,35 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
if(is_unsigned_samples) {
if(channels == 2) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000);
u16buffer[sample++] = (FLAC__uint16)(buffer[1][wide_sample] + 0x8000);
ubuf.u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000);
ubuf.u16buffer[sample++] = (FLAC__uint16)(buffer[1][wide_sample] + 0x8000);
}
}
else if(channels == 1) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000);
ubuf.u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000);
}
else { /* works for any 'channels' but above flavors are faster for 1 and 2 */
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
ubuf.u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
}
}
else {
if(channels == 2) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
s16buffer[sample++] = (FLAC__int16)(buffer[1][wide_sample]);
ubuf.s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
ubuf.s16buffer[sample++] = (FLAC__int16)(buffer[1][wide_sample]);
}
}
else if(channels == 1) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
ubuf.s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
}
else { /* works for any 'channels' but above flavors are faster for 1 and 2 */
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
ubuf.s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
}
}
if(is_big_endian != is_big_endian_host_) {
@@ -1164,9 +1168,9 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
const unsigned bytes = sample * 2;
unsigned b;
for(b = 0; b < bytes; b += 2) {
tmp = u8buffer[b];
u8buffer[b] = u8buffer[b+1];
u8buffer[b+1] = tmp;
tmp = ubuf.u8buffer[b];
ubuf.u8buffer[b] = ubuf.u8buffer[b+1];
ubuf.u8buffer[b+1] = tmp;
}
}
bytes_to_write = 2 * sample;
@@ -1175,24 +1179,24 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
if(is_unsigned_samples) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
ubuf.u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
}
else {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
s32buffer[sample] = buffer[channel][wide_sample];
ubuf.s32buffer[sample] = buffer[channel][wide_sample];
}
if(is_big_endian != is_big_endian_host_) {
unsigned char tmp;
const unsigned bytes = sample * 4;
unsigned b;
for(b = 0; b < bytes; b += 4) {
tmp = u8buffer[b];
u8buffer[b] = u8buffer[b+3];
u8buffer[b+3] = tmp;
tmp = u8buffer[b+1];
u8buffer[b+1] = u8buffer[b+2];
u8buffer[b+2] = tmp;
tmp = ubuf.u8buffer[b];
ubuf.u8buffer[b] = ubuf.u8buffer[b+3];
ubuf.u8buffer[b+3] = tmp;
tmp = ubuf.u8buffer[b+1];
ubuf.u8buffer[b+1] = ubuf.u8buffer[b+2];
ubuf.u8buffer[b+2] = tmp;
}
}
if(is_big_endian) {
@@ -1200,18 +1204,18 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
const unsigned bytes = sample * 4;
for(lbyte = b = 0; b < bytes; ) {
b++;
u8buffer[lbyte++] = u8buffer[b++];
u8buffer[lbyte++] = u8buffer[b++];
u8buffer[lbyte++] = u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
}
}
else {
unsigned b, lbyte;
const unsigned bytes = sample * 4;
for(lbyte = b = 0; b < bytes; ) {
u8buffer[lbyte++] = u8buffer[b++];
u8buffer[lbyte++] = u8buffer[b++];
u8buffer[lbyte++] = u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
ubuf.u8buffer[lbyte++] = ubuf.u8buffer[b++];
b++;
}
}
@@ -1221,12 +1225,12 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
if(is_unsigned_samples) {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
ubuf.u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
}
else {
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
ubuf.s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
}
bytes_to_write = sample;
}
@@ -1239,7 +1243,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
}
}
if(bytes_to_write > 0) {
if(flac__utils_fwrite(u8buffer, 1, bytes_to_write, fout) != bytes_to_write) {
if(flac__utils_fwrite(ubuf.u8buffer, 1, bytes_to_write, fout) != bytes_to_write) {
/* if a pipe closed when writing to stdout, we let it go without an error message */
if(errno == EPIPE && decoder_session->fout == stdout)
decoder_session->aborting_due_to_until = true;