
/*	Copyright (C) G. Jespersen
	See Licence.txt.*/

#if !defined CDAREAD_H
#define CDAREAD_H

#if _MSC_VER > 1000
#pragma once
#endif				// _MSC_VER > 1000

// Some test code - not using - works - could use to copy CD Tracks to wave file.
// From:
//	https://www.codeproject.com/Articles/15725/Tutorial-on-reading-Audio-CDs
// Used while developing AsyncCD Filter.

// For track storage.
//#include <valarray>
//#include <vector>

#define CD_BLOCKS_PER_SECOND 75
#define SECTORS_AT_READ		20
#define RAW_SECTOR_SIZE		2352
#define CD_SECTOR_SIZE		2048
#define RIFFID				'FFIR' 
#define WAVEID				'EVAW' 
#define FormatID			' tmf' 
#define DataID				'atad'

//#define MSF2UINT(hgs) ((hgs[1] * 4500) + (hgs[2] * 75) + (hgs[3]))

struct CHUNKHEADER
{
	CHUNKHEADER() { Zero(); };
	UINT chunkID; 
	long chunkSize;
	void Zero() { chunkID = 0; chunkSize = 0; };
};
struct RIFFCHUNCK
{
	RIFFCHUNCK() { Zero(); };
	CHUNKHEADER hdr; 
	UINT WAVE;
	void Zero() { hdr.Zero(); WAVE = 0; };
};
struct FORMATCHUNK
{
	FORMATCHUNK() { Zero(); };
	CHUNKHEADER hdr; 
	PCMWAVEFORMAT pcm;
	void Zero() { hdr.Zero(); ZeroMemory(&pcm, sizeof(PCMWAVEFORMAT)); };
};
struct DATACHUNK
{
	DATACHUNK() { Zero(); };
	CHUNKHEADER hdr;
	void Zero() { hdr.Zero(); };
};
struct WAVECHUNK
{
	WAVECHUNK() { Zero(); };
	RIFFCHUNCK riff; 
	FORMATCHUNK frm; 
	DATACHUNK data;
	void Zero() { riff.Zero(); frm.Zero(); data.Zero(); };
};


/* Defined in ntddcdrm.h - DDK
#define MAXIMUM_NUMBER_TRACKS	100
#define IOCTL_CDROM_READ_TOC	0x24000
typedef struct _TRACK_DATA - TRACK_DATA
typedef struct _CDROM_TOC - CDROM_TOC */

// Structure to hold the basic information for a cd-track
struct CDTRACK
{
	CDTRACK() { Zero(); };
	ULONG Address;
	ULONG Length;
	int TrackNumber;
	void Zero() { Address = 0; Length = 0; TrackNumber = 0; };
};

///////////////////////////////////////////////////
// Class CCdaRead
class CCdaRead
{
public:
	CCdaRead();
	~CCdaRead();

	BOOL OpenCdaFile(CString cdaFile);
	BOOL ExtractTrack(int iTrack, CString filePath);

private:
	BOOL ReadDrive(CString drive);

	// Msf: Hours, Minutes, Seconds, Frames
	ULONG AddressToSectors(UCHAR Addr[4]);

public:
	// Track storage
	CArray<CDTRACK, CDTRACK&> m_tracks;

	// Members
	HANDLE	m_hDrive;
	CString m_fileName;
	CString m_drive;
	int m_iTrack;
};

///////////////////////////////////////////////////
// Class CWaveFileHeader - a tiny class that helps 
// us creating the header of a wave-file.
class CWaveFileHeader
{
	public:
		CWaveFileHeader();
		CWaveFileHeader( ULONG SamplingRate, USHORT BitsPerSample, USHORT Channels, ULONG DataSize );
		void Set( ULONG SamplingRate, USHORT BitsPerSample, USHORT Channels, ULONG DataSize );

	private:
		UCHAR  m_Riff_ID[4];		//'RIFF'
		ULONG  m_Riff_Size;			// FileSize-8
		UCHAR  m_Riff_Type[4];		// 'WAVE'

		UCHAR  m_Fmt_ID[4];			// 'FMT '
		ULONG  m_Fmt_Length;		// 16
		USHORT m_Fmt_Format;		// 1 (=MS PCM)
		USHORT m_Fmt_Channels;		// 1 = mono, 2 = stereo
		ULONG  m_Fmt_SamplingRate;	// Abtastrate pro Sekunde (z.B. 44100)
		ULONG  m_Fmt_DataRate;		// SamplingRate * BlockAlign
		USHORT m_Fmt_BlockAlign;	// Channels * BitsPerSample / 8
		USHORT m_Fmt_BitsPerSample;	// 8 or 16

		UCHAR  m_Data_ID[4];		// 'data'
		ULONG  m_Data_DataSize;		// Size of the following data
};

///////////////////////////////////////////////////
// Class CBuf - allocates and free's a buffer.
template<class Cl> class CBuf
{
	public:
		CBuf()
		{
			m_pData = NULL;
			m_iSize = 0;
		}
		CBuf(ULONG Count)
		{
			m_pData = (Cl*)malloc( (m_iSize = Count) * sizeof(Cl) );
		}
		~CBuf()
		{
			Free();
		}

		Cl* Alloc(ULONG Count)
		{
			return m_pData = (Cl*) realloc( m_pData, (m_iSize=Count)*sizeof(Cl) );
		}
		void Free()
		{
			free(m_pData); // null ok
			m_pData = NULL;
			m_iSize = 0;
		}
		ULONG Count()
		{
			return m_iSize;
		}
		ULONG Size()
		{
			return m_iSize * sizeof(Cl);
		}
		Cl* Ptr()
		{
			return m_pData;
		}
		operator Cl* ()
		{
			return m_pData;
		}
	private:
		Cl*		m_pData;
		ULONG	m_iSize;
};


#endif // CDAREAD_H

