Index: dsfilters/demux_mpc/src/mpc_file.cpp
===================================================================
--- dsfilters/demux_mpc/src/mpc_file.cpp	(revision 378)
+++ dsfilters/demux_mpc/src/mpc_file.cpp	(revision 379)
@@ -7,5 +7,5 @@
 //-----------------------------------------------------------------------------
 #include "stdafx.h"
-
+#include <math.h>
 
 
@@ -25,4 +25,10 @@
 	extradata_size = 0;
 	extradata = (uint8*)malloc(extradata_max_size);
+	bits_to_skip = 0;
+
+	gain_album_db = 0;
+	gain_album_peak_db = 0;
+	gain_title_db = 0;
+	gain_title_peak_db = 0;
 }
 
@@ -93,5 +99,5 @@
 		reader->GetPosition(&first_ap_pos, &avail);
 
-		reader->Seek(seek_table_position);
+		reader->Seek(seek_table_position/8);
 		ret = packet.Load(reader);
 		ret = ReadSeekTable(&packet); 
@@ -126,14 +132,18 @@
 
 	uint8		hdr[8*4];
+	
+	__int64 c, a;
+	reader->GetPosition(&c, &a);
 	ret = reader->Read(extradata + 4, 6*4);
 	if (ret < 0) return -1;			// not enough data
-	memcpy(hdr, extradata+4, 5*4);
 	extradata_size += 6*4;
+	reader->Seek(c);
+	ret = reader->ReadSwapped(hdr, 6*4);
 	Bitstream	b(hdr);
 
-	b.NeedBits32_MPC();
-	audio_block_frames = (b.UGetBits(16)<<16) | b.UGetBits(16);
-
-	b.NeedBits32_MPC();
+	b.NeedBits32();
+	int audio_frames = (b.UGetBits(16)<<16) | b.UGetBits(16);
+
+	b.NeedBits32();
 	b.UGetBits(1);				// intensity stereo, should be 0
 	b.UGetBits(1);				// mid-side
@@ -153,18 +163,35 @@
 	b.UGetBits(16);				// max-level
 
-	b.NeedBits32_MPC();
-	gain_title_db = b.SGetBits(16) / 100.0;				// title gain
-	gain_title_peak_db = b.UGetBits(16);		// title peak
-
-	b.NeedBits32_MPC();
-	gain_album_db = b.SGetBits(16) / 100.0;				// album gain
-	gain_album_peak_db = b.UGetBits(16);		// album peak
-
-
-
-	b.NeedBits32_MPC();
+	b.NeedBits32();
+	gain_title_db = b.SGetBits(16) / 100.0;		// title gain
+	int title_peak = b.UGetBits(16);
+	if (title_peak != 0) {
+		gain_title_peak_db = 20 * log10f((float)title_peak);		// title peak
+	} else {
+		gain_title_peak_db = 0;
+	}
+
+	b.NeedBits32();
+	gain_album_db = b.SGetBits(16) / 100.0;		// album gain
+	int album_peak = b.UGetBits(16);
+	if (album_peak != 0) {
+		gain_album_peak_db = 20 * log10f((float)album_peak);		// album peak
+	} else {
+		gain_album_peak_db = 0;
+	}
+
+	#define OLD_GAIN_REF		64.82
+	if (gain_title_db != 0) {
+		gain_title_db = OLD_GAIN_REF - gain_title_db;
+	}
+	if (gain_album_db != 0) {
+		gain_album_db = OLD_GAIN_REF - gain_album_db;
+	}
+
+	b.NeedBits32();
 	true_gapless = b.UGetBits(1);			// true gapless
 	int last_frame = b.UGetBits(11);		// last-frame samples
-	total_samples = (audio_block_frames * 1152);
+	audio_block_frames = 1;
+	total_samples = (audio_frames * 1152);
 	if (true_gapless) {
 		total_samples -= (1152 - last_frame);
@@ -178,5 +205,5 @@
 	b.UGetBits(3);
 
-	b.NeedBits32_MPC();
+	b.NeedBits32();
 	int ver = b.UGetBits(8);
 
@@ -192,14 +219,37 @@
 
 	// alloc memory for seek table
-	seek_table = (uint32*)malloc(tmp * sizeof(uint32));
+	seek_table = (uint64*)malloc(tmp * sizeof(uint64));
 	if (!seek_table) return -1;
 
 	int64 pos, av;
 	reader->GetPosition(&pos, &av);
-	seek_table[0] = pos*8;		// current position in bits
+	seek_table[0] = pos*8 - b.BitsLeft();		// current position in bits
 	seek_table_size = 1;
 
-	// TODO: loop through file to get complete seeking table
-
+	// loop through file to get complete seeking table
+	CMPCPacket	packet;
+	int64 seek_frames = 0;
+	Seek(0);
+	do {
+		if (seek_frames*1152 >= total_samples) break;
+
+		// new entry in seeking table
+		if (seek_frames == (seek_table_size << seek_pwr)) {
+			__int64 c, a;
+			reader->GetPosition(&c, &a);
+			seek_table[seek_table_size] = (c*8) + bits_to_skip;
+			seek_table_size++;
+		}
+
+		ret = packet.Load_SV7(reader, bits_to_skip, true);
+		if (ret<0) break;
+		seek_frames += 1;
+	} while (true);
+
+	// seek to begin
+	Seek(0);
+
+	header_position = 0;
+	bits_to_skip = 0;
 	return 0;
 }
@@ -261,5 +311,5 @@
 	Bitstream	b(packet->payload);
 
-	seek_table_position = b.GetMpcSize();
+	seek_table_position = b.GetMpcSize() * 8;
 	seek_table_position += packet->file_position;
 
@@ -280,14 +330,14 @@
 
 	// alloc memory for seek table
-	seek_table = (uint32*)malloc(tmp * sizeof(uint32));
-
-	uint32 *table = seek_table;
+	seek_table = (uint64*)malloc(tmp * sizeof(uint64));
+
+	uint64 *table = seek_table;
 
 	tmp = b.GetMpcSize();
-	table[0] = (uint32)(tmp + header_position) * 8;
+	table[0] = (uint32)(tmp*8 + header_position);
 	if (seek_table_size == 1) return 0;
 
 	tmp = b.GetMpcSize();
-	table[1] = (uint32)(tmp + header_position) * 8;
+	table[1] = (uint64)(tmp*8 + header_position);
 	for (int i=2; i<seek_table_size; i++) {
 		int code = b.Get_Golomb(12);
@@ -316,17 +366,4 @@
 
 	switch (stream_version) {
-	case 7:
-		{
-			//-----------------------------------------------------------------
-			//	Stream Version 7
-			//-----------------------------------------------------------------
-
-			// since we don't do any actual decoding here, we can only look 
-			// for the fields of our interest
-
-			// TODO: later. now we want SV8
-
-		}
-		break;
 	case 8:
 		{
@@ -361,5 +398,5 @@
 
 			// store absolute position of stream header
-			header_position = packet->file_position -4;
+			header_position = packet->file_position - 4*8;
 		}
 		break;
@@ -379,24 +416,35 @@
 	int ret;
 
+	// end of file ?
+	if (current_sample >= total_samples) return -2;
+
 	do {
-		ret = packet->Load(reader);
+		switch (stream_version) {
+		case 7:	ret = packet->Load_SV7(reader, bits_to_skip); break;
+		case 8: ret = packet->Load(reader); break;
+		default: ret = -2; break;
+		}
 		if (ret < 0) {
 			return ret;
 		}
 
-		switch (packet->key) {
-		case MPC_KEY('A','P'):	
-			{
-				// keep track of samples...
-				if (cur_sample) *cur_sample = current_sample;
-				current_sample += (1152*audio_block_frames);
-
-				return 0;			// we got one
+		// keep track of samples...
+		if (cur_sample) *cur_sample = current_sample;
+		if (stream_version == 8) {
+			switch (packet->key) {
+			case MPC_KEY('A','P'):	
+				{
+					current_sample += (1152*audio_block_frames);
+					return 0;			// we got one
+				}
+			case MPC_KEY('S','E'):
+				{
+					return -2;
+				}
+				break;
 			}
-		case MPC_KEY('S','E'):
-			{
-				return -2;
-			}
-			break;
+		} else {
+			current_sample += (1152*audio_block_frames);
+			return 0;
 		}
 
@@ -438,7 +486,6 @@
 
 	// seek to position
-	uint32 pos = seek_table[i] >> 3;
-	CString f;
-	f.Format(_T("CMPCFile::Seek : %d"), pos);
+	uint64 pos = seek_table[i] >> 3;
+	bits_to_skip = seek_table[i] & 0x07;
 	reader->Seek(pos);
 
@@ -483,4 +530,85 @@
 }
 
+int CMPCPacket::Load_SV7(CMPCReader *reader, int &bits_to_skip, bool only_parse)
+{
+	uint8	temp[14*1024];
+	uint8	outtemp[14*1024];
+	__int64	cur, av;
+	int		t;
+	int		total_bits;
+
+	Release();
+
+	reader->GetPosition(&cur, &av);
+	int ret = reader->ReadSwapped(temp, min(sizeof(temp), (av-cur)));
+	if (ret < 0) return 0;
+
+	Bitstream	b(temp);
+	Bitstream	o(outtemp);
+	b.NeedBits32();
+
+	// We load bits from input file and store it into our buffer.
+	// There they will always start at byte alignment so they can 
+	// be transferred to decoder in a pleasant way.
+
+	// skip bits from previous frame
+	if (bits_to_skip > 0) {	b.DumpBits(bits_to_skip); }
+	file_position = (cur*8) + bits_to_skip;
+
+	// 20-bit frame length
+	b.NeedBits24();
+	int	frame_len_bits = b.UGetBits(20);
+	o.PutBits(frame_len_bits, 20);
+
+	if (only_parse == false) {
+		// load data
+		int left_bits = frame_len_bits;
+		while (left_bits > 16) {
+			b.NeedBits();
+			t = b.UGetBits(16);
+			o.PutBits(t, 16);
+			left_bits -= 16;
+		}
+		b.NeedBits();
+		t = b.UGetBits(left_bits);
+		o.PutBits(t, left_bits);
+
+		// zero-align 32-bit word
+		total_bits = (20 + frame_len_bits + 31) &~ 31;
+		int zero_bits = total_bits - frame_len_bits;
+		o.PutBits(0, zero_bits);
+		o.WriteBits();
+	}
+
+	// bits to skip in the next frame
+	__int64 finalpos = file_position + 20 + frame_len_bits;
+	bits_to_skip = (finalpos & 7);
+	reader->Seek(finalpos >> 3);
+
+	// copy data
+	if (only_parse == false) {
+		packet_size  = total_bits >> 3;
+		payload_size = packet_size;
+		packet = (uint8*)malloc(packet_size);
+		payload = packet;				// pointer to packet payload
+
+		// copy data
+		uint8 *src = outtemp;
+		uint8 *dst = packet;
+		int left = packet_size;
+		while (left > 3) {
+			dst[0] = src[3];
+			dst[1] = src[2];
+			dst[2] = src[1];
+			dst[3] = src[0];
+			src += 4;
+			dst += 4;
+			left-= 4;
+		}
+	}
+
+	return 0;
+}
+
 int CMPCPacket::Load(CMPCReader *reader)
 {
@@ -493,21 +621,15 @@
 
 	// end of stream
-	if (file_position >= avail) {
-		return -2;
-	}
+	if (file_position >= avail) return -2;
+	file_position *= 8;
 
 	ret = reader->GetKey(key_val);					
-	if (ret < 0) {
-		return ret;
-	}
+	if (ret < 0) return ret;
+
 	ret = reader->GetSizeElm(size_val, size_len);	
-	if (ret < 0) {
-		return ret;
-	}
+	if (ret < 0) return ret;
 
 	// if the key is not valid, quit
-	if (!reader->KeyValid(key_val)) {
-		return -1;
-	}
+	if (!reader->KeyValid(key_val)) return -1;
 	key = key_val;
 
@@ -519,12 +641,9 @@
 
 	// roll back the bytes
-	reader->Seek(file_position);
+	reader->Seek(file_position/8);
 	ret = reader->Read(packet, packet_size);		
-	if (ret < 0) {
-		return ret;
-	}
-
-	return 0;
-}
-
-
+	if (ret < 0) return ret;
+	return 0;
+}
+
+
