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

205 lines
5.7 KiB
C++

/*
* BitWriter.h
*
* Description: Bit writer 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 BitWriter
{
protected:
HANDLE hOutFile;
unsigned long start_offset;
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 lastpos;
public:
unsigned long output_byte_count;
BitWriter(HANDLE fd, unsigned long offset) :
frame_crc32(0xFFFFFFFFUL),
start_offset(offset), hOutFile (fd),
bit_count(0), bit_cache(0),
bitpos (bit_buffer), lastpos (0), output_byte_count (0),
bit_buffer_end (bit_buffer + BIT_BUFFER_SIZE)
{
SetFilePointer (hOutFile, start_offset, NULL, FILE_BEGIN);
}
virtual ~BitWriter(void) {}
virtual void PutHeader (TTAHeader ttahdr)
{
unsigned long result;
ttahdr.TTAid = ENDSWAP_INT32(TTA1_SIGN);
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);
ttahdr.CRC32 = crc32((unsigned char *) &ttahdr,
sizeof(TTAHeader) - sizeof(long));
ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32);
// write TTA header
if (!WriteFile(hOutFile, &ttahdr, sizeof(TTAHeader), &result, NULL) ||
result != sizeof (TTAHeader))
{
CloseHandle (hOutFile);
throw TTAException (WRITE_ERROR);
}
lastpos = (output_byte_count += sizeof(TTAHeader));
}
virtual void PutSeekTable (unsigned long *seek_table, long st_size)
{
unsigned long result;
unsigned long *st;
if (SetFilePointer (hOutFile, 0, NULL, FILE_CURRENT) != start_offset + sizeof(TTAHeader))
SetFilePointer (hOutFile, start_offset + sizeof(TTAHeader), NULL, FILE_BEGIN);
else
lastpos = (output_byte_count += st_size * sizeof(long));
for (st = seek_table; st < (seek_table + st_size - 1); st++)
*st = ENDSWAP_INT32(*st);
seek_table[st_size - 1] = crc32((unsigned char *) seek_table,
(st_size - 1) * sizeof(long));
seek_table[st_size - 1] = ENDSWAP_INT32(seek_table[st_size - 1]);
if (!WriteFile(hOutFile, seek_table, st_size * sizeof(long), &result, NULL) ||
result != st_size * sizeof(long))
{
CloseHandle (hOutFile);
throw TTAException (WRITE_ERROR);
}
}
virtual void PutBinary(unsigned long value, unsigned long bits)
{
while (bit_count >= 8) {
if (bitpos == bit_buffer_end) {
unsigned long result;
if (!WriteFile (hOutFile, bit_buffer, BIT_BUFFER_SIZE, &result, NULL) ||
result != BIT_BUFFER_SIZE)
throw TTAException (WRITE_ERROR);
output_byte_count += result;
bitpos = bit_buffer;
}
*bitpos = (unsigned char) (bit_cache & 0xFF);
UPDATE_CRC32(*bitpos, frame_crc32);
bit_cache >>= 8;
bit_count -= 8;
bitpos++;
}
bit_cache |= (value & bit_mask[bits]) << bit_count;
bit_count += bits;
}
virtual void PutUnary(unsigned long value)
{
do {
while (bit_count >= 8) {
if (bitpos == bit_buffer_end) {
unsigned long result;
if (!WriteFile (hOutFile, bit_buffer, BIT_BUFFER_SIZE, &result, NULL) ||
result != BIT_BUFFER_SIZE)
throw TTAException (WRITE_ERROR);
output_byte_count += result;
bitpos = bit_buffer;
}
*bitpos = (unsigned char) (bit_cache & 0xFF);
UPDATE_CRC32(*bitpos, frame_crc32);
bit_cache >>= 8;
bit_count -= 8;
bitpos++;
}
if (value > 23) {
bit_cache |= bit_mask[23] << bit_count;
bit_count += 23;
value -= 23;
} else {
bit_cache |= bit_mask[value] << bit_count;
bit_count += value + 1;
value = 0;
}
} while (value);
}
virtual int Done()
{
unsigned long res, bytes_to_write;
while (bit_count) {
*bitpos = (unsigned char) (bit_cache & 0xFF);
UPDATE_CRC32(*bitpos, frame_crc32);
bit_cache >>= 8;
bit_count = (bit_count > 8) ? (bit_count - 8) : 0;
bitpos++;
}
frame_crc32 ^= 0xFFFFFFFFUL;
frame_crc32 = ENDSWAP_INT32(frame_crc32);
CopyMemory(bitpos, &frame_crc32, 4);
bytes_to_write = bitpos + sizeof(long) - bit_buffer;
if (!WriteFile(hOutFile, bit_buffer, bytes_to_write, &res, NULL) ||
res != bytes_to_write)
throw TTAException (WRITE_ERROR);
output_byte_count += res;
bitpos = bit_buffer;
frame_crc32 = 0xFFFFFFFFUL;
res = output_byte_count - lastpos;
lastpos = output_byte_count;
return res;
}
};
};