windows-nt/Source/XPSP1/NT/multimedia/media/deluxe2/cdopt/cdread.cpp
2020-09-26 16:20:57 +08:00

366 lines
10 KiB
C++

// cdread.cpp
//
#include <windows.h>
#include <windowsx.h>
#include <TCHAR.H>
#include <mmsystem.h>
#include "cdread.h"
#include "cddata.h"
#include "..\main\resource.h"
#include "..\main\sink.h"
#include "mmreg.h"
#include "msacm.h"
HANDLE hFile = NULL;
LPCDDATA pData = NULL;
TIMEDMETER tm;
DWORD dwTotalBytes = 0;
WAVEFORMATEX wfxPCM1, wfxPCM2;
DWORD cbOutBytes[3];
HACMSTREAM acmStream[3];
ACMSTREAMHEADER acmHeader[3];
BYTE sSample[CDDA_SECTOR_SIZE * SECTORS_PER_READ];
BYTE sCompBuffer[CDDA_SECTOR_SIZE * SECTORS_PER_READ];
// Write a WAV header for the selected format
BOOL writeHeader(int iSize, LPWAVEFORMATEX lpwfx)
{
DWORD dwBytesWritten = 0;
unsigned data, formatdata;
WORD wData;
WriteFile(hFile,"RIFF",4,&dwBytesWritten,NULL);
formatdata = 16;
if ((lpwfx->wFormatTag != WAVE_FORMAT_PCM) && (lpwfx->cbSize > 0))
{
formatdata += sizeof(WORD); //to write cdSize out
formatdata += lpwfx->cbSize;
}
data = 0x24 + iSize + (formatdata-16);
WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
WriteFile(hFile,"WAVE",4,&dwBytesWritten,NULL);
WriteFile(hFile,"fmt ",4,&dwBytesWritten,NULL);
WriteFile(hFile,&formatdata,sizeof(unsigned),&dwBytesWritten,NULL);
WriteFile(hFile,lpwfx,formatdata,&dwBytesWritten,NULL);
/*
wData = lpwfx->wFormatTag;
WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
wData = lpwfx->nChannels;
WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
data = lpwfx->nSamplesPerSec;
WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
data = lpwfx->nAvgBytesPerSec;
WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
wData = lpwfx->nBlockAlign;
WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
wData = lpwfx->wBitsPerSample;
WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
if ((lpwfx->wFormatTag != WAVE_FORMAT_PCM) && (lpwfx->cbSize > 0))
{
wData = lpwfx->cbSize;
WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
pData = (BYTE*)(&(lpwfx->cbSize) + sizeof(WORD));
WriteFile(hFile,pData,lpwfx->cbSize,&dwBytesWritten,NULL);
}
*/
WriteFile(hFile,"data",4,&dwBytesWritten,NULL);
data = iSize;
WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
return TRUE;
}
BOOL readTOC( HANDLE hDevice, PCDROM_TOC pToc )
{
DWORD dwTocSize = sizeof(CDROM_TOC);
DWORD dwBytesReturned = 0;
DWORD dwNumTracks = 0;
if( !DeviceIoControl( hDevice,
IOCTL_CDROM_READ_TOC,
pToc, // pointer to inputbuffer
dwTocSize, // sizeof inputbuffer
pToc, // pointer to outputbuffer
dwTocSize, // sizeof outputbuffer
&dwBytesReturned, // pointer to number of bytes returned
FALSE
)
)
{
return FALSE;
}
dwNumTracks = pToc->LastTrack - pToc->FirstTrack;
//
// number of tracks plus zero-based plus leadout track
//
if ( (dwNumTracks+2) * sizeof(TRACK_DATA) != dwBytesReturned - 4 )
{
dwNumTracks = (dwBytesReturned - 4) / sizeof(TRACK_DATA);
}
// parse and print the information
PTRACK_DATA pTrack = (PTRACK_DATA) &(pToc->TrackData[0]);
return TRUE;
}
BOOL skipRead( BYTE* buffer, DWORD dwSize, int iPercent )
{
return TRUE;
}
BOOL writeRead( BYTE* buffer, DWORD dwSize, int iPercent )
{
DWORD dwBytesWritten = 0;
if (pData)
{
pData->UpdateMeter(&tm);
}
acmStreamConvert(acmStream[0],&acmHeader[0],0);
acmStreamConvert(acmStream[1],&acmHeader[1],0);
acmStreamConvert(acmStream[2],&acmHeader[2],0);
WriteFile(hFile,sCompBuffer,acmHeader[2].cbDstLengthUsed,&dwBytesWritten,NULL);
dwTotalBytes += dwBytesWritten;
return TRUE;
}
BOOL rawReadTrack(HANDLE device, PCDROM_TOC pTOC, int iTrack, LPREADFUNC lpReadFunc )
{
RAW_READ_INFO info; // fill in for the read request
DWORD dwBytesRead; // bytes returned
DWORD dwStartingLBA;
DWORD dwNumLBA;
DWORD dwEndingLBA;
DWORD dwSectorsToRead;
DWORD dwError;
PTRACK_DATA pTrack = (PTRACK_DATA) &(pTOC->TrackData[0]);
PTRACK_DATA pTrack2;
// Use VirtualAlloc so we get a page-aligned region since we're doing
// non-cached IO
/*
sSample = (BYTE*)VirtualAlloc(NULL, PAGE_VAL, MEM_COMMIT, PAGE_READWRITE );
if( !sSample )
{
//MessageBox( NULL, "Error allocating memory block.", "Error", MB_OK );
return FALSE;
}
*/
pTrack += (iTrack-1);
pTrack2 = pTrack + 1;
dwStartingLBA = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
dwEndingLBA = MSF_TO_LBA( pTrack2->Address[1], pTrack2->Address[2], pTrack2->Address[3] );
dwNumLBA = dwEndingLBA-dwStartingLBA;
//
// round up the num sectors to read
//
dwSectorsToRead = ((dwNumLBA - 1) / SECTORS_PER_READ + 1) * SECTORS_PER_READ;
dwEndingLBA = dwStartingLBA + dwSectorsToRead;
// start the read loop
for ( DWORD i = dwStartingLBA; i < dwEndingLBA; i += SECTORS_PER_READ )
{
int iPercent;
info.DiskOffset.QuadPart = (unsigned __int64)(i*2048);
info.SectorCount = SECTORS_PER_READ;
info.TrackMode = CDDA;
if( !DeviceIoControl( device,
IOCTL_CDROM_RAW_READ,
&info, // pointer to inputbuffer
sizeof(RAW_READ_INFO), // sizeof inputbuffer
sSample, // pointer to outputbuffer
CDDA_SECTOR_SIZE * SECTORS_PER_READ, // sizeof outputbuffer
&dwBytesRead, // pointer to number of bytes returned
FALSE // ???
)
)
{
goto fail;
}
iPercent = (i-dwStartingLBA)/(dwEndingLBA-dwStartingLBA);
if( !((*lpReadFunc)(sSample, dwBytesRead, iPercent) ) )
{
goto fail;
}
}
//VirtualFree( sSample, PAGE_VAL, MEM_DECOMMIT );
return TRUE;
fail:
VirtualFree( sSample, PAGE_VAL, MEM_DECOMMIT );
return FALSE;
}
// Find the byte size of a track
int getTrackSize( PCDROM_TOC pTOC, int iTrack )
{
PTRACK_DATA pTrack = &(pTOC->TrackData[0]);
DWORD dwLBA1, dwLBA2;
pTrack += (iTrack-1);
dwLBA1 = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
pTrack++;
dwLBA2 = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
return (dwLBA2-dwLBA1) * CDDA_SECTOR_SIZE;
}
BOOL StoreTrack(HWND hwndMain, TCHAR chDrive, int nTrack, TCHAR* pszFilename, LPWAVEFORMATEX lpwfxDest)
{
HANDLE hDevice;
TCHAR szDeviceName[MAX_PATH];
CDROM_TOC sTOC;
wsprintf( szDeviceName, TEXT("\\\\.\\%c:"), chDrive );
hDevice = CreateFile( szDeviceName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( INVALID_HANDLE_VALUE == hDevice )
{
return FALSE;
}
readTOC( hDevice, &sTOC );
int iSize = getTrackSize( &sTOC, nTrack );
dwTotalBytes = 0;
WAVEFORMATEX waveFormat;
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = 44100;
waveFormat.nAvgBytesPerSec = 176400;
waveFormat.nBlockAlign = 4;
waveFormat.wBitsPerSample = 16;
waveFormat.cbSize = sizeof(waveFormat);
wfxPCM1.wFormatTag = WAVE_FORMAT_PCM;
acmFormatSuggest(NULL, &waveFormat, &wfxPCM1, sizeof(WAVEFORMATEX),
ACM_FORMATSUGGESTF_WFORMATTAG);
wfxPCM2.wFormatTag = WAVE_FORMAT_PCM;
acmFormatSuggest(NULL, lpwfxDest, &wfxPCM2, sizeof(WAVEFORMATEX),
ACM_FORMATSUGGESTF_WFORMATTAG);
acmStreamOpen(&acmStream[0],NULL,&waveFormat,&wfxPCM1,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
acmStreamOpen(&acmStream[1],NULL,&wfxPCM1,&wfxPCM2,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
acmStreamOpen(&acmStream[2],NULL,&wfxPCM2,lpwfxDest,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
acmStreamSize(acmStream[0],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[0],ACM_STREAMSIZEF_SOURCE);
acmStreamSize(acmStream[1],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[1],ACM_STREAMSIZEF_SOURCE);
acmStreamSize(acmStream[2],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[2],ACM_STREAMSIZEF_SOURCE);
acmHeader[0].cbStruct = sizeof(acmHeader);
acmHeader[0].fdwStatus = 0;
acmHeader[0].dwUser = 0;
acmHeader[0].pbSrc = sSample;
acmHeader[0].cbSrcLength = CDDA_SECTOR_SIZE * SECTORS_PER_READ;
acmHeader[0].pbDst = sCompBuffer;
acmHeader[0].cbDstLength = cbOutBytes[0];
acmHeader[0].dwDstUser = 0;
acmHeader[1].cbStruct = sizeof(acmHeader);
acmHeader[1].fdwStatus = 0;
acmHeader[1].dwUser = 0;
acmHeader[1].pbSrc = sCompBuffer;
acmHeader[1].cbSrcLength = cbOutBytes[0];
acmHeader[1].pbDst = sSample;
acmHeader[1].cbDstLength = cbOutBytes[1];
acmHeader[1].dwDstUser = 0;
acmHeader[2].cbStruct = sizeof(acmHeader);
acmHeader[2].fdwStatus = 0;
acmHeader[2].dwUser = 0;
acmHeader[2].pbSrc = sSample;
acmHeader[2].cbSrcLength = cbOutBytes[1];
acmHeader[2].pbDst = sCompBuffer;
acmHeader[2].cbDstLength = cbOutBytes[2];
acmHeader[2].dwDstUser = 0;
acmStreamPrepareHeader(acmStream[0],&acmHeader[0],0);
acmStreamPrepareHeader(acmStream[1],&acmHeader[1],0);
acmStreamPrepareHeader(acmStream[2],&acmHeader[2],0);
hFile = CreateFile(pszFilename,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
//write a temp header. we'll need to write a new one later when we know the right file size
if( !writeHeader( iSize, lpwfxDest ) )
{
CloseHandle( hFile );
return FALSE;
}
pData = GetCDData();
if (pData)
{
pData->CreateMeter(&tm,hwndMain,(iSize / (CDDA_SECTOR_SIZE * SECTORS_PER_READ)),5,IDS_RIPPING_CD);
}
rawReadTrack( hDevice, &sTOC, nTrack, writeRead );
if (pData)
{
pData->DestroyMeter(&tm);
}
acmStreamUnprepareHeader(acmStream[0],&acmHeader[0],0);
acmStreamUnprepareHeader(acmStream[1],&acmHeader[1],0);
acmStreamUnprepareHeader(acmStream[2],&acmHeader[2],0);
acmStreamClose(acmStream[0],0);
acmStreamClose(acmStream[1],0);
acmStreamClose(acmStream[2],0);
CloseHandle( hDevice );
SetFilePointer(hFile,0,NULL,FILE_BEGIN);
if( !writeHeader( dwTotalBytes, lpwfxDest ) )
{
CloseHandle( hFile );
return FALSE;
}
CloseHandle( hFile );
return TRUE;
}