diff options
author | Robert Kausch <robert.kausch@freac.org> | 2018-04-30 12:13:46 +0200 |
---|---|---|
committer | Erik de Castro Lopo <erikd@mega-nerd.com> | 2018-05-21 10:19:03 +1000 |
commit | 8874ecc082ae2e5201998647ad8c0621502a322c (patch) | |
tree | 2cccc9238dec4634b938dc3b314462a73290bd52 | |
parent | 5579f2922f048aa3bd2b206dd64f6ead2846c8ac (diff) | |
download | flac-8874ecc082ae2e5201998647ad8c0621502a322c.tar.gz |
Update CRC16 for larger data blocks when decoding.
-rw-r--r-- | src/libFLAC/bitreader.c | 61 | ||||
-rw-r--r-- | src/libFLAC/crc.c | 40 | ||||
-rw-r--r-- | src/libFLAC/include/private/crc.h | 2 |
3 files changed, 75 insertions, 28 deletions
diff --git a/src/libFLAC/bitreader.c b/src/libFLAC/bitreader.c index baafcf33..683e9f84 100644 --- a/src/libFLAC/bitreader.c +++ b/src/libFLAC/bitreader.c @@ -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; } diff --git a/src/libFLAC/crc.c b/src/libFLAC/crc.c index cb08f137..faa34965 100644 --- a/src/libFLAC/crc.c +++ b/src/libFLAC/crc.c @@ -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; +} diff --git a/src/libFLAC/include/private/crc.h b/src/libFLAC/include/private/crc.h index 8d3d456b..5fc7e5ee 100644 --- a/src/libFLAC/include/private/crc.h +++ b/src/libFLAC/include/private/crc.h @@ -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 |