src/flac/decode.c : Fix a cast-align warning from GCC.
authorErik de Castro Lopo <erikd@mega-nerd.com>
Fri, 27 Jun 2014 11:58:26 +0000 (21:58 +1000)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Fri, 27 Jun 2014 12:06:39 +0000 (22:06 +1000)
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.

src/flac/decode.c

index 3f08c21..771c36b 100644 (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;