#ifndef MP3_H
#define MP3_H

/*
 * @(#)MP3.h
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 2002 Jörg P. M. Haeger
 *
 * webCDwriter is free software. See CDWserver.cpp for details.
 */

#include "File.h"
#include "FileInputStream.h"

/**
 * A class to handle MP3 files.
 *
 * @version 20021017
 * @author Jörg P. M. Haeger
 */
class MP3 {
private:
	int format;
	int channels;
	long frequency;
	long bytesPerSecond;
	int bytesPerSample;
	long dataLength;
	long firstHeaderStart;
	int MPEGVersion;
	int layer;
	int bitrate;

public:
	MP3(File &file) {
		static const int kbps[2][3][15] = { {
		{1, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448},
		{1, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384},
		{1, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320}
		}, {
		{1, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256},
		{1,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160},
		{1,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160}
		}
		};

		FileInputStream inStream = new FileInputStream(file);
		firstHeaderStart = 0;
		while (true) {
			int b = inStream.read();
			if (b == -1)
				throw new Exception("is not a MP3");
			if (b != 0xFF) {
				firstHeaderStart++;
				continue;
			}
			b = inStream.read();
			if (b < 0xF0) {
				firstHeaderStart += 2;
				continue;
			}
			switch (b & 0x08) {
				case 0x00: MPEGVersion = 2; break;
				case 0x08: MPEGVersion = 1; break;
			}
			switch (b & 0x06) {
				case 0x00: layer = 0; break;
				case 0x02: layer = 3; break;
				case 0x04: layer = 2; break;
				case 0x06: layer = 1; break;
			}
			b = inStream.read();
			if (b >= 0xF0) {
				firstHeaderStart += 3;
				continue;
			}
			bitrate = kbps[MPEGVersion - 1][layer - 1][(b & 0xF0) >> 4];
			if (MPEGVersion == 1)
				switch (b & 0x0C) {
					case 0x00: frequency = 44100; break;
					case 0x04: frequency = 48000; break;
					case 0x08: frequency = 32000; break;
					case 0x0C: frequency = -1; break;
				}
			else
			if (MPEGVersion == 2)
				switch (b & 0x0C) {
					case 0x00: frequency = 22050; break;
					case 0x04: frequency = 24000; break;
					case 0x08: frequency = 16000; break;
					case 0x0C: frequency = -1; break;
				}
			b = inStream.read();
			switch (b & 0xC0) {
				case 0x00: channels = 2; break;
				case 0x40: channels = 2; break;
				case 0x80: channels = 2; break;
				case 0xC0: channels = 1; break;
			}
			break;
		}
		dataLength = file.getSize();
		bytesPerSecond = 1000 * bitrate / 8;
	}

	long getSeconds() {
		if (bytesPerSecond > 0)
			return dataLength / bytesPerSecond;
		else
			return 0;
	}
};

#endif
