CAFE

공유 강좌

WAV를 PCM으로 변환하기

작성자미니|작성시간06.04.12|조회수2,419 목록 댓글 0
웨이브 파일의 PCM 데이터를 읽어서 그대로 바이너리 파일로 저장하도록

작성하였으므로 웨이브 파일이 PCM포맷일 때만 바이너리 PCM 파일로 저장할 수

있습니다. (아닌 경우는 변환 불가 메시지박스가 뜹니다.)



PCM포맷이 아닌 경우는 ACM 라이브러리를 사용해서 디코딩해야 하나 여기서는

생략하였습니다.



Win32 윈도우 애플리케이션으로 만들었지만 메인 윈도우는 만들지 않았습니다.



명령프롬프트(혹은 MS-DOS)창에서 변환하고자 하는 파일 이름을 같이 입력하면

확장자가 .pcm이 되는 파일로 변환이 됩니다. 만일 변환 대상 파일 이름을 같이 입력

하지 않으면 파일 열기 다이얼로그박스가 열리므로 거기서 선택하면 됩니다.



이 프로그램은 winmm.lib와 같이 링크되어야 합니다.



// Wav2PCM.cpp : Wave to PCM Converter
// winmm.lib are required when linking



#include <windows.h>
#include <mmsystem.h>



#define IO_SAMPLES 2048



BOOL GetWaveFileName(LPSTR lpFileName, int cbFileName, LPSTR lpCmdLine);
void SetDefExtension(LPSTR lpFileName, LPCSTR lpDefExt, BOOL bForce);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
char szWaveName[_MAX_PATH], szPcmName[_MAX_PATH];



if(!GetWaveFileName(szWaveName, sizeof(szWaveName), lpCmdLine))
return 0;



strcpy(szPcmName, szWaveName);
SetDefExtension(szPcmName, ".pcm", TRUE);



HMMIO hmmio;
MMCKINFO mmckRiff, mmck;
LPWAVEFORMATEX lpwfx;
LONG cbwfx;
LONG nTotalSamples;



hmmio = mmioOpen((LPTSTR)szWaveName, NULL, MMIO_READ | MMIO_ALLOCBUF);
if(hmmio == NULL) {
MessageBox(NULL, "파일을 열 수 없습니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}



mmckRiff.fccType = mmioStringToFOURCC("WAVE", 0);
if(mmioDescend(hmmio, &mmckRiff, NULL, MMIO_FINDRIFF)) {
mmioClose(hmmio, 0);
MessageBox(NULL, "웨이브 파일이 아닙니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}



mmck.ckid = mmioStringToFOURCC("fmt ", 0);
if(mmioDescend(hmmio, &mmck, &mmckRiff, MMIO_FINDCHUNK)) {
mmioClose(hmmio, 0);
MessageBox(NULL, "웨이브 포맷을 찾을 수 없습니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}



cbwfx = mmck.cksize;
lpwfx = (LPWAVEFORMATEX)new BYTE[cbwfx];
if(mmioRead(hmmio, (HPSTR)lpwfx, cbwfx) < 0) {
delete [] lpwfx;
mmioClose(hmmio, 0);
MessageBox(NULL, "웨이브 포맷을 읽을 수 없습니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}
mmioAscend(hmmio, &mmck, 0);



if((lpwfx->wFormatTag != WAVE_FORMAT_PCM)) {
delete [] lpwfx;
mmioClose(hmmio, 0);
MessageBox(NULL, "PCM 포맷이 아닙니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}



nTotalSamples = 0;

mmck.ckid = mmioStringToFOURCC("fact", 0);
if(mmioDescend(hmmio, &mmck, &mmckRiff, MMIO_FINDCHUNK) == MMSYSERR_NOERROR) {
mmioRead(hmmio, (LPSTR)&nTotalSamples, mmck.cksize);
mmioAscend(hmmio, &mmck, 0);
}
else {
mmioSeek(hmmio, 0, SEEK_SET);
mmckRiff.fccType = mmioStringToFOURCC("WAVE", 0);
mmioDescend(hmmio, &mmckRiff, NULL, MMIO_FINDRIFF);
}



mmck.ckid = mmioStringToFOURCC("data", 0);
if(mmioDescend(hmmio, &mmck, &mmckRiff, MMIO_FINDCHUNK)) {
delete [] lpwfx;
mmioClose(hmmio, 0);
MessageBox(NULL, "웨이브 데이터를 찾을 수 없습니다.", "Wav2PCM", MB_OK | MB_ICONSTOP);
return 0;
}



if(nTotalSamples == 0)
nTotalSamples = MulDiv(mmck.cksize, lpwfx->nSamplesPerSec, lpwfx->nAvgBytesPerSec);



HANDLE hFile = CreateFile(szPcmName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
delete [] lpwfx;
mmioClose(hmmio, 0);
MessageBox(NULL, "출력 파일을 만들 수 없습니다.", "Error", MB_OK | MB_ICONSTOP);
return 0;
}



LONG cbBuffer = lpwfx->nBlockAlign * IO_SAMPLES;
LPBYTE lpBuffer = new BYTE[cbBuffer];


while(TRUE) {
LONG lReadBytes = mmioRead(hmmio, (HPSTR)lpBuffer, cbBuffer);
if(lReadBytes <= 0) break;
DWORD dwWritten;
WriteFile(hFile, lpBuffer, lReadBytes, &dwWritten, NULL);
}
delete [] lpBuffer;
CloseHandle(hFile);

delete [] lpwfx;
mmioClose(hmmio, 0);



MessageBox(NULL, "변환을 완료하였습니다.", "Wav2PCM", MB_OK | MB_ICONINFORMATION);
return 0;
}



BOOL GetWaveFileName(LPSTR lpFileName, int cbFileName, LPSTR lpCmdLine)
{
if(lpCmdLine[0] == '\0') {
lpFileName[0] = '\0';
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFilter = "Wave Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0\0";
ofn.lpstrFile = lpFileName;
ofn.nMaxFile = cbFileName;
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
if(!GetOpenFileName(&ofn)) return FALSE;
}
else if(lpCmdLine[0] == '\"') {
char *sp = strchr(lpCmdLine + 1, '\"');
if(sp != NULL) *sp = '\0';
strcpy(lpFileName, lpCmdLine + 1);
}
else {
char *sp = strchr(lpCmdLine, ' ');
if(sp != NULL) *sp = '\0';
strcpy(lpFileName, lpCmdLine);
}
return TRUE;
}



void SetDefExtension(LPSTR lpFileName, LPCSTR lpDefExt, BOOL bForce)
{
char szDrv[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];
_splitpath(lpFileName, szDrv, szDir, szFname, szExt);
if(bForce || szExt[0] == 0) strcpy(szExt, lpDefExt);
_makepath(lpFileName, szDrv, szDir, szFname, szExt);
}

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼