Update CRC16 for larger data blocks when decoding.
authorRobert Kausch <robert.kausch@freac.org>
Mon, 30 Apr 2018 10:13:46 +0000 (12:13 +0200)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Mon, 21 May 2018 00:19:03 +0000 (10:19 +1000)
src/libFLAC/bitreader.c
src/libFLAC/crc.c
src/libFLAC/include/private/crc.h

index baafcf3..683e9f8 100644 (file)
@@ -1,6 +1,6 @@
 /* libFLAC - Free Lossless Audio Codec library
  * Copyright (C) 2000-2009  Josh Coalson
- * Copyright (C) 2011-2016  Xiph.Org Foundation
+ * Copyright (C) 2011-2018  Xiph.Org Foundation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -109,6 +109,7 @@ struct FLAC__BitReader {
        uint32_t consumed_words; /* #words ... */
        uint32_t consumed_bits; /* ... + (#bits of head word) already consumed from the front of buffer */
        uint32_t read_crc16; /* the running frame CRC */
+       uint32_t crc16_offset; /* the number of words in the current buffer that should not be CRC'd */
        uint32_t crc16_align; /* the number of bits in the current consumed word that should not be CRC'd */
        FLAC__BitReaderReadCallback read_callback;
        void *client_data;
@@ -117,32 +118,33 @@ struct FLAC__BitReader {
 static inline void crc16_update_word_(FLAC__BitReader *br, brword word)
 {
        register uint32_t crc = br->read_crc16;
-#if FLAC__BYTES_PER_WORD == 4
-       switch(br->crc16_align) {
-               case  0: crc = FLAC__CRC16_UPDATE((uint32_t)(word >> 24), crc); /* Falls through. */
-               case  8: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 16) & 0xff), crc); /* Falls through. */
-               case 16: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 8) & 0xff), crc); /* Falls through. */
-               case 24: br->read_crc16 = FLAC__CRC16_UPDATE((uint32_t)(word & 0xff), crc); /* Falls through. */
-       }
-#elif FLAC__BYTES_PER_WORD == 8
-       switch(br->crc16_align) {
-               case  0: crc = FLAC__CRC16_UPDATE((uint32_t)(word >> 56), crc); /* Falls through. */
-               case  8: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 48) & 0xff), crc); /* Falls through. */
-               case 16: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 40) & 0xff), crc); /* Falls through. */
-               case 24: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 32) & 0xff), crc); /* Falls through. */
-               case 32: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 24) & 0xff), crc); /* Falls through. */
-               case 40: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 16) & 0xff), crc); /* Falls through. */
-               case 48: crc = FLAC__CRC16_UPDATE((uint32_t)((word >> 8) & 0xff), crc); /* Falls through. */
-               case 56: br->read_crc16 = FLAC__CRC16_UPDATE((uint32_t)(word & 0xff), crc);
-       }
-#else
+
        for( ; br->crc16_align < FLAC__BITS_PER_WORD; br->crc16_align += 8)
                crc = FLAC__CRC16_UPDATE((uint32_t)((word >> (FLAC__BITS_PER_WORD-8-br->crc16_align)) & 0xff), crc);
+
        br->read_crc16 = crc;
-#endif
        br->crc16_align = 0;
 }
 
+static inline void crc16_update_block_(FLAC__BitReader *br)
+{
+       if(br->crc16_align)
+               crc16_update_word_(br, br->buffer[br->crc16_offset++]);
+
+#if FLAC__BYTES_PER_WORD == 4
+       br->read_crc16 = FLAC__crc16_update_words32(br->buffer + br->crc16_offset, br->consumed_words - br->crc16_offset, br->read_crc16);
+#elif FLAC__BYTES_PER_WORD == 8
+       br->read_crc16 = FLAC__crc16_update_words64(br->buffer + br->crc16_offset, br->consumed_words - br->crc16_offset, br->read_crc16);
+#else
+       unsigned i;
+
+       for(i = br->crc16_offset; i < br->consumed_words; i++)
+               crc16_update_word_(br, br->buffer[i]);
+#endif
+
+       br->crc16_offset = 0;
+}
+
 static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br)
 {
        uint32_t start, end;
@@ -151,6 +153,8 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br)
 
        /* first shift the unconsumed buffer data toward the front as much as possible */
        if(br->consumed_words > 0) {
+               crc16_update_block_(br); /* CRC consumed words */
+
                start = br->consumed_words;
                end = br->words + (br->bytes? 1:0);
                memmove(br->buffer, br->buffer+start, FLAC__BYTES_PER_WORD * (end - start));
@@ -328,6 +332,7 @@ void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed)
        FLAC__ASSERT((br->consumed_bits & 7) == 0);
 
        br->read_crc16 = (uint32_t)seed;
+       br->crc16_offset = br->consumed_words;
        br->crc16_align = br->consumed_bits;
 }
 
@@ -335,6 +340,10 @@ FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br)
 {
        FLAC__ASSERT(0 != br);
        FLAC__ASSERT(0 != br->buffer);
+
+       /* CRC consumed words up to here */
+       crc16_update_block_(br);
+
        FLAC__ASSERT((br->consumed_bits & 7) == 0);
        FLAC__ASSERT(br->crc16_align <= br->consumed_bits);
 
@@ -397,7 +406,6 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
                        /* (FLAC__BITS_PER_WORD - br->consumed_bits <= bits) ==> (FLAC__WORD_ALL_ONES >> br->consumed_bits) has no more than 'bits' non-zero bits */
                        *val = (FLAC__uint32)(word & (FLAC__WORD_ALL_ONES >> br->consumed_bits));
                        bits -= n;
-                       crc16_update_word_(br, word);
                        br->consumed_words++;
                        br->consumed_bits = 0;
                        if(bits) { /* if there are still bits left to read, there have to be less than 32 so they will all be in the next word */
@@ -416,7 +424,6 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va
                        }
                        /* at this point bits == FLAC__BITS_PER_WORD == 32; because of previous assertions, it can't be larger */
                        *val = (FLAC__uint32)word;
-                       crc16_update_word_(br, word);
                        br->consumed_words++;
                        return true;
                }
@@ -663,7 +670,6 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
                                i++;
                                br->consumed_bits += i;
                                if(br->consumed_bits >= FLAC__BITS_PER_WORD) { /* faster way of testing if(br->consumed_bits == FLAC__BITS_PER_WORD) */
-                                       crc16_update_word_(br, br->buffer[br->consumed_words]);
                                        br->consumed_words++;
                                        br->consumed_bits = 0;
                                }
@@ -671,7 +677,6 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
                        }
                        else {
                                *val += FLAC__BITS_PER_WORD - br->consumed_bits;
-                               crc16_update_word_(br, br->buffer[br->consumed_words]);
                                br->consumed_words++;
                                br->consumed_bits = 0;
                                /* didn't find stop bit yet, have to keep going... */
@@ -789,7 +794,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
                        x = ucbits;
                        do {
                                /* didn't find stop bit yet, have to keep going... */
-                               crc16_update_word_(br, br->buffer[cwords++]);
+                               cwords++;
                                if (cwords >= words)
                                        goto incomplete_msbs;
                                b = br->buffer[cwords];
@@ -809,7 +814,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
                        b <<= parameter;
                } else {
                        /* there are still bits left to read, they will all be in the next word */
-                       crc16_update_word_(br, br->buffer[cwords++]);
+                       cwords++;
                        if (cwords >= words)
                                goto incomplete_lsbs;
                        b = br->buffer[cwords];
@@ -865,7 +870,7 @@ incomplete_lsbs:
 
        if(ucbits == 0 && cwords < words) {
                /* don't leave the head word with no unconsumed bits */
-               crc16_update_word_(br, br->buffer[cwords++]);
+               cwords++;
                ucbits = FLAC__BITS_PER_WORD;
        }
 
index cb08f13..faa3496 100644 (file)
@@ -394,3 +394,43 @@ FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len)
 
        return crc;
 }
+
+FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc)
+{
+       while (len >= 2) {
+               crc ^= words[0] >> 16;
+
+               crc = FLAC__crc16_table[7][crc >> 8               ] ^ FLAC__crc16_table[6][crc & 0xFF             ] ^
+                     FLAC__crc16_table[5][(words[0] >>  8) & 0xFF] ^ FLAC__crc16_table[4][ words[0]        & 0xFF] ^
+                     FLAC__crc16_table[3][ words[1] >> 24        ] ^ FLAC__crc16_table[2][(words[1] >> 16) & 0xFF] ^
+                     FLAC__crc16_table[1][(words[1] >>  8) & 0xFF] ^ FLAC__crc16_table[0][ words[1]        & 0xFF];
+
+               words += 2;
+               len -= 2;
+       }
+
+       if (len) {
+               crc ^= words[0] >> 16;
+
+               crc = FLAC__crc16_table[3][crc >> 8               ] ^ FLAC__crc16_table[2][crc & 0xFF             ] ^
+                     FLAC__crc16_table[1][(words[0] >>  8) & 0xFF] ^ FLAC__crc16_table[0][words[0]         & 0xFF];
+       }
+
+       return crc;
+}
+
+FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc)
+{
+       while (len--) {
+               crc ^= words[0] >> 48;
+
+               crc = FLAC__crc16_table[7][crc >> 8               ] ^ FLAC__crc16_table[6][crc & 0xFF             ] ^
+                     FLAC__crc16_table[5][(words[0] >> 40) & 0xFF] ^ FLAC__crc16_table[4][(words[0] >> 32) & 0xFF] ^
+                     FLAC__crc16_table[3][(words[0] >> 24) & 0xFF] ^ FLAC__crc16_table[2][(words[0] >> 16) & 0xFF] ^
+                     FLAC__crc16_table[1][(words[0] >>  8) & 0xFF] ^ FLAC__crc16_table[0][ words[0]        & 0xFF];
+
+               words++;
+       }
+
+       return crc;
+}
index 8d3d456..5fc7e5e 100644 (file)
@@ -54,5 +54,7 @@ extern FLAC__uint16 const FLAC__crc16_table[8][256];
 #endif
 
 FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len);
+FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc);
+FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc);
 
 #endif