WAVE 을 녹음하고 재생하는 소스인대요
이것을 DELPHI로 변환을 할려구 하는대 안되요...
고수님의 도음을 부탁드립니다....
// Wave.cpp: Implementierung der Klasse CWave.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////
CWave::CWave()
{
pFmt = pData = NULL;
}
CWave::~CWave()
{
Stop(); // stop playing, recording
delete pFmt; delete pData; // free memory
}
bool CWave::Read(char * fname)
{
HMMIO hmmio; // file handle for open file
MMCKINFO ciParentChunk; // parent chunk information
MMCKINFO ciSubChunk; // subchunk information structure
Stop(); // just in case
delete pFmt; delete pData; // free memory
// wav-Datei f? gepufferte I/O (8 kByte) ?fnen
hmmio = mmioOpen(fname, NULL, MMIO_READ | MMIO_ALLOCBUF);
if(!hmmio) {
MessageBox(NULL, "Failed to open file.", NULL, MB_OK);
return false;
}
// WAVE-Abschnitt suchen
mmioSeek(hmmio, 0, SEEK_SET ); // reset to beginning of file.
ciParentChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmioDescend(hmmio, (LPMMCKINFO) &ciParentChunk, NULL, MMIO_FINDRIFF)) {
MessageBox(NULL, "Not a waveform-audio file.", NULL, MB_OK);
mmioClose(hmmio, 0);
return false;
}
// jedes 'Waveform-Audio' enth?t einen 'fmt'- und einen
// 'data'-Abschnitt, zun?hst wird der 'fmt'-Abschnitt betreten
ciSubChunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hmmio, &ciSubChunk, &ciParentChunk, MMIO_FINDCHUNK)) {
MessageBox(NULL, "Unable to locate 'fmt' chunk.", NULL, MB_OK);
mmioClose(hmmio, 0);
return false;
}
// Speicher f? 'fmt'-Abschnitt vorbereiten
nFmtSize = ciSubChunk.cksize;
pFmt = new BYTE[nFmtSize];
memset(pFmt,NULL,nFmtSize);
// 'fmt'-Abschnitt lesen
if (mmioRead(hmmio, (HPSTR)pFmt, nFmtSize) != nFmtSize) {
MessageBox(NULL, "Error reading 'fmt' chunk.", NULL, MB_OK);
delete pFmt;
mmioClose(hmmio, 0);
return false;
}
// 'fmt'-Abschnitt verlassen
mmioAscend(hmmio, &ciSubChunk, 0);
// 'data'-Abschnitt betreten
ciSubChunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hmmio, &ciSubChunk, &ciParentChunk, MMIO_FINDCHUNK)) {
MessageBox(NULL, "Unable to locate 'data' chunk.", NULL, MB_OK);
delete pFmt;
mmioClose(hmmio, 0);
return false;
}
// Speicher f? 'data'-Abschnitt anlegen
nDataSize = ciSubChunk.cksize;
pData = new BYTE[nDataSize];
// 'data'-Abschnitt lesen
if(mmioRead(hmmio, (HPSTR)pData, nDataSize) != nDataSize) {
MessageBox(NULL, "Error reading 'data' chunk.", NULL, MB_OK);
delete pFmt; delete pData;
mmioClose(hmmio, 0);
return false;
}
// RIFF-Datei schlie?n
mmioClose(hmmio, 0);
return true;
}
bool CWave::Play(HWND hWnd)
{
static WAVEHDR WaveHdr;
if (!pFmt) // nothing to play
return false;
// open waveform-audio driver
Stop();
MMRESULT rc = waveOutOpen(&hwo, 0, (LPWAVEFORMATEX)pFmt,
(DWORD)hWnd, 0L, CALLBACK_WINDOW);
if (rc != MMSYSERR_NOERROR) {
MessageBox(NULL, "Unable to open waveform-audio driver.", NULL, MB_OK);
return false;
}
// configure WAVEHDR
WaveHdr.lpData = (char*) pData;
WaveHdr.dwBufferLength = nDataSize;
WaveHdr.dwFlags = WaveHdr.dwLoops = 0L;
// prepare, write, and unprepre WAVEHDR
waveOutPrepareHeader(hwo, &WaveHdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &WaveHdr, sizeof(WAVEHDR));
return true;
}
void CWave::Stop()
{
waveInReset(hwi);
waveInClose(hwi);
waveOutReset(hwo);
waveOutClose(hwo);
}
CString CWave::Info()
{
CString i = "keine Datei geladen";
WAVEFORMATEX *w= (WAVEFORMATEX*) pFmt;
if (w)
if (w->wFormatTag == WAVE_FORMAT_PCM)
i.Format("Kan?e: %d, nAbtastrate: %d, nSample: %d Bit",
(int) w->nChannels,
(int) w->nSamplesPerSec,
(int) w->wBitsPerSample);
else
i="kann den wave-codec nicht interpretieren";
return i;
}
void CWave::Draw(CDC *dc, CRect rect, long offset, char channel) {
//Rechteck
dc->MoveTo(rect.TopLeft());
dc->LineTo(rect.right,rect.top);
dc->LineTo(rect.BottomRight());
dc->LineTo(rect.left,rect.bottom);
dc->LineTo(rect.TopLeft());
if (!pFmt) return; // nothing to draw
WAVEFORMATEX *w = (WAVEFORMATEX*) pFmt;
int x = rect.left; //x-Position
int y = rect.top+(rect.bottom-rect.top)/2;
dc->MoveTo(x++,y); //Stift setzen
short int value16, max16=0x7FFF; // f? 16 Bit Samples
unsigned char value8, max8=0x7F; // f? 8 Bit Samples
long i=offset*((int)w->nChannels)*((int)w->wBitsPerSample/8);
if ((channel == 'r') && ((int)w->nChannels ==2))
i += w->wBitsPerSample/8;
dc->MoveTo(x++, y);
for (;x<=rect.right; x++) {
if (i>=nDataSize) break; //end of sound
if ((int)w->wBitsPerSample == 16) {
y = rect.top + (rect.bottom-rect.top)/2;
value16= *((short int*)(pData + i));
y -= (int) ((float)value16/max16 * ((rect.bottom-rect.top)/2));
} else {
y = rect.bottom;
value8 = *((unsigned char*)(pData + i));
y -= (int) ((float)value8/max8 * ((rect.bottom-rect.top)/2));
}
dc->LineTo(x,y);
i += ((int)w->nChannels)*((int)w->wBitsPerSample/8);
}
}
bool CWave::Save(CString fname)
{
HMMIO hmmio; // file handle for open file
MMCKINFO ciRiffChunk; // main RIFF chunk information
MMCKINFO ciSubChunk; // subchunk information
MMIOINFO mmioInfo;
MMRESULT rc;
if (!pFmt) return false; // nothing to save
// rename a prev. wav-file (if one exists)
mmioRename(fname, fname+".orig", NULL, 0);
// open the wave file using an internal I/O buffer
memset(&mmioInfo, 0, sizeof(mmioInfo)); // set struct to zero
mmioInfo.fccIOProc = mmioStringToFOURCC("WAV ", 0);
hmmio = mmioOpen((char*) LPCTSTR(fname), &mmioInfo,MMIO_CREATE | MMIO_WRITE | MMIO_ALLOCBUF);
if(!hmmio) {
MessageBox(NULL, "Failed to open file.", NULL, MB_OK);
return false;
}
// attempt to increase the size of the buffer to 128K
mmioSetBuffer(hmmio, NULL, 131072, 0);
// create main 'RIFF' chunk
mmioSeek(hmmio, 0, SEEK_SET); // reset to beginning of file.
ciRiffChunk.fccType = mmioFOURCC('W', 'A', 'V', 'E');
ciRiffChunk.cksize = 0L; // mmio will determine corect size
rc = mmioCreateChunk(hmmio, &ciRiffChunk, MMIO_CREATERIFF);
// create 'fmt' chunk
ciSubChunk.ckid = mmioStringToFOURCC("fmt ", 0);
ciSubChunk.cksize = sizeof(WAVEFORMATEX);
rc = mmioCreateChunk(hmmio, &ciSubChunk, 0);
rc = mmioWrite(hmmio, (char*) pFmt, sizeof(WAVEFORMATEX));
// ascend out of 'fmt' chunk back to the main 'RIFF' chunk
rc = mmioAscend(hmmio, &ciSubChunk, 0);
// create 'data' chunk
// if the cksize is incorrect, when we ascend out of the chunk,
// the cksize will be updated to it's actual size
ciSubChunk.ckid = mmioStringToFOURCC("data", 0);
ciSubChunk.cksize = nDataSize;
rc = mmioCreateChunk(hmmio, &ciSubChunk, 0);
// okay, now lets write the data to the buffer
rc = mmioWrite(hmmio, (char*) pData, nDataSize);
// ascend out of 'data' chunk back to the main 'RIFF' chunk
// this corrects the chunk length if not correctly
// specified when the chunk was created.
rc = mmioAscend(hmmio, &ciSubChunk, 0);
// ascend out of the main 'RIFF' chunk
rc = mmioAscend(hmmio, &ciRiffChunk, 0);
// flush buffer and close file
rc = mmioFlush(hmmio, 0);
rc = mmioClose(hmmio, 0);
// you have to check rc after each mmio-Call !!!
return true;
}
bool CWave::Record(HWND hWnd) {
static WAVEHDR WaveHdr;
if (!pFmt) return false; //no parameters
//open waveform-driver
MMRESULT rc = waveInOpen(&hwi, 0, (LPWAVEFORMATEX) pFmt,(DWORD) hWnd, 0L, CALLBACK_WINDOW);
if (rc != MMSYSERR_NOERROR) {
AfxMessageBox("Unable to open audio driver");
return false;
}
WaveHdr.lpData=(char*) pData;
WaveHdr.dwBufferLength=nDataSize;
WaveHdr.dwFlags = WaveHdr.dwLoops = 0;
waveInPrepareHeader(hwi,&WaveHdr, sizeof(WaveHdr));
waveInAddBuffer(hwi,&WaveHdr, sizeof(WaveHdr));
waveInStart(hwi);
return true;
}
bool CWave::Create(int nSamplesPerSec, int wBitsPerSample,
int nChannels, int nSeconds) {
// Test, ob Parameter plausibel sind
if (((nSamplesPerSec != 8000) && (nSamplesPerSec != 11025) &&
(nSamplesPerSec != 22050) && (nSamplesPerSec != 44100)) ||
((nChannels != 1) && (nChannels != 2)) ||
((wBitsPerSample != 8) && (wBitsPerSample != 16)))
return false;
Stop();
delete pFmt; delete pData;
//Speicher f? fmt-Abschnitt vorbereiten
WAVEFORMATEX *w = new WAVEFORMATEX;
pFmt = (BYTE*) w;
nFmtSize = sizeof(WAVEFORMATEX);
w->wFormatTag = WAVE_FORMAT_PCM;
w->nChannels= nChannels;
w->nSamplesPerSec=nSamplesPerSec;
w->wBitsPerSample=wBitsPerSample;
w->nBlockAlign=nChannels*wBitsPerSample/8;
w->nAvgBytesPerSec=nSamplesPerSec*w->nBlockAlign;
w->cbSize=0;
//Speicher f? data-Abschnitt
nDataSize=w->nAvgBytesPerSec*nSeconds;
pData = new BYTE[nDataSize];
memset(pData,NULL,nDataSize);
return true;
}