summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Kausch <robert.kausch@freac.org>2018-04-30 12:13:46 +0200
committerErik de Castro Lopo <erikd@mega-nerd.com>2018-05-21 10:19:03 +1000
commit8874ecc082ae2e5201998647ad8c0621502a322c (patch)
tree2cccc9238dec4634b938dc3b314462a73290bd52
parent5579f2922f048aa3bd2b206dd64f6ead2846c8ac (diff)
downloadflac-8874ecc082ae2e5201998647ad8c0621502a322c.tar.gz
Update CRC16 for larger data blocks when decoding.
-rw-r--r--src/libFLAC/bitreader.c61
-rw-r--r--src/libFLAC/crc.c40
-rw-r--r--src/libFLAC/include/private/crc.h2
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