Files
cuetools.net/ttalib-1.1/BitReader.h
2009-01-15 23:15:04 +00:00

200 lines
5.1 KiB
C++

/*
* BitReader.h
*
* Description: Bit reader internal interface
*
* Copyright (c) 2004 Alexander Djourik. All rights reserved.
* Copyright (c) 2004 Pavel Zhilin. All rights reserved.
*
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* aint with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Please see the file COPYING in this directory for full copyright
* information.
*/
#pragma once
#include <windows.h>
#include "TTACommon.h"
#include "TTAError.h"
#include "crc32.h"
namespace TTALib
{
class BitReader
{
protected:
HANDLE hInFile;
unsigned char bit_buffer[BIT_BUFFER_SIZE + 8];
unsigned char *bit_buffer_end;
unsigned long frame_crc32;
unsigned long bit_count;
unsigned long bit_cache;
unsigned char *bitpos;
unsigned long *st;
unsigned long next_frame_pos;
public:
BitReader(HANDLE fd) :
frame_crc32(0xFFFFFFFFUL), hInFile (fd),
bit_count(0), bit_cache(0), bit_buffer_end(bit_buffer + BIT_BUFFER_SIZE),
bitpos(bit_buffer_end), input_byte_count (0)
{
}
virtual ~BitReader(void) {}
virtual void GetHeader (TTAHeader *ttahdr)
{
unsigned long result, checksum;
if (!ReadFile(hInFile, ttahdr, sizeof(TTAHeader), &result, NULL) ||
result != sizeof (TTAHeader))
{
throw TTAException (READ_ERROR);
} else input_byte_count += sizeof(*ttahdr);
// check for supported formats
if (ENDSWAP_INT32(ttahdr->TTAid) != TTA1_SIGN)
throw TTAException (FORMAT_ERROR);
checksum = crc32((unsigned char *) ttahdr, sizeof(TTAHeader) - sizeof(long));
if (checksum != ttahdr->CRC32)
throw TTAException (FILE_ERROR);
ttahdr->AudioFormat = ENDSWAP_INT16(ttahdr->AudioFormat);
ttahdr->NumChannels = ENDSWAP_INT16(ttahdr->NumChannels);
ttahdr->BitsPerSample = ENDSWAP_INT16(ttahdr->BitsPerSample);
ttahdr->SampleRate = ENDSWAP_INT32(ttahdr->SampleRate);
ttahdr->DataLength = ENDSWAP_INT32(ttahdr->DataLength);
}
virtual bool GetSeekTable (unsigned long *seek_table, long st_size)
{
unsigned long result, checksum;
bool st_state = false;
if (!ReadFile(hInFile, seek_table, st_size * sizeof(long), &result, NULL) ||
result != st_size * sizeof(long))
throw TTAException (READ_ERROR);
else input_byte_count += st_size * sizeof(long);
checksum = crc32((unsigned char *) seek_table, (st_size - 1) * sizeof(long));
if (checksum == ENDSWAP_INT32(seek_table[st_size - 1]))
st_state = true;
for (st = seek_table; st < (seek_table + st_size); st++)
*st = ENDSWAP_INT32(*st);
next_frame_pos = SetFilePointer (hInFile, 0, NULL, FILE_CURRENT);
st = seek_table;
return st_state;
}
virtual void GetBinary(unsigned long *value, unsigned long bits) {
while (bit_count < bits) {
if (bitpos == bit_buffer_end) {
unsigned long result;
if (!ReadFile (hInFile, bit_buffer, BIT_BUFFER_SIZE, &result, NULL))
throw TTAException (READ_ERROR);
input_byte_count += result;
bitpos = bit_buffer;
}
UPDATE_CRC32(*bitpos, frame_crc32);
bit_cache |= *bitpos << bit_count;
bit_count += 8;
bitpos++;
}
*value = bit_cache & bit_mask[bits];
bit_cache >>= bits;
bit_count -= bits;
bit_cache &= bit_mask[bit_count];
}
virtual void GetUnary(unsigned long *value)
{
*value = 0;
while (!(bit_cache ^ bit_mask[bit_count])) {
if (bitpos == bit_buffer_end) {
unsigned long result;
if (!ReadFile (hInFile, bit_buffer, BIT_BUFFER_SIZE, &result, NULL))
throw TTAException (READ_ERROR);
input_byte_count += result;
bitpos = bit_buffer;
}
*value += bit_count;
bit_cache = *bitpos++;
UPDATE_CRC32(bit_cache, frame_crc32);
bit_count = 8;
}
while (bit_cache & 1) {
(*value)++;
bit_cache >>= 1;
bit_count--;
}
bit_cache >>= 1;
bit_count--;
}
virtual int Done ()
{
unsigned long crc32, rbytes, result;
frame_crc32 ^= 0xFFFFFFFFUL;
next_frame_pos += *st++;
rbytes = bit_buffer_end - bitpos;
if (rbytes < sizeof(long)) {
CopyMemory(bit_buffer, bitpos, 4);
if (!ReadFile(hInFile, bit_buffer + rbytes,
BIT_BUFFER_SIZE - rbytes, &result, NULL))
throw TTAException (READ_ERROR);
input_byte_count += result;
bitpos = bit_buffer;
}
CopyMemory(&crc32, bitpos, 4);
crc32 = ENDSWAP_INT32(crc32);
bitpos += sizeof(long);
result = (crc32 != frame_crc32);
bit_cache = bit_count = 0;
frame_crc32 = 0xFFFFFFFFUL;
return result;
}
virtual void SkipFrame ()
{
SetFilePointer(hInFile, next_frame_pos, NULL, FILE_BEGIN);
bitpos = bit_buffer_end;
}
unsigned long input_byte_count;
};
};