//open the wave out device and allocate wavOutBuffer
long waveOpenOut(void)
{
    MMRESULT wresult;
    lphWaveOut = &hWaveOut;     //wave handle
    lpwfOut = &pwfOut;          //wave format
    pwfOut.wFormatTag=WAVE_FORMAT_PCM;
    pwfOut.nChannels=2;
    pwfOut.nSamplesPerSec=SAMPLES;
    pwfOut.nAvgBytesPerSec=SAMPLES*2*BITS/8;
    pwfOut.nBlockAlign=2*BITS/8;
    pwfOut.wBitsPerSample=BITS;
    pwfOut.cbSize = 0;
    wresult = waveOutOpen(lphWaveOut,WAVE_MAPPER,lpwfOut,(DWORD) cbWaveOutProc,(DWORD) 0,(DWORD) CALLBACK_FUNCTION | WAVE_ALLOWSYNC );
    hOutData = GlobalAlloc(GMEM_MOVEABLE,BUFFERLENGTH*4);
    wavOutBuffer = (short *)GlobalLock(hOutData);
    hOutHdr = GlobalAlloc(GMEM_MOVEABLE,sizeof(WAVEHDR));
    lpwoh = (LPWAVEHDR)GlobalLock(hOutHdr);
    lpwoh->lpData = (LPSTR)wavOutBuffer;
    lpwoh->dwBufferLength=BUFFERLENGTH*4;
    lpwoh->dwFlags=0;
    return (long)wresult;
}
//close the wave out device and free the wavOutBuffer
long waveCloseOut(void)
{
    MMRESULT wresult;
    wresult = waveOutReset(hWaveOut);
    wresult += waveOutClose(hWaveOut);
    GlobalUnlock(hOutData);
    hOutData = GlobalFree(hOutData);
    GlobalUnlock(hOutHdr);
    hOutHdr = GlobalFree(hOutHdr);
    return (long) wresult;
}
//open the wave in device and allocate the wavInBuffer
long waveOpenIn(void)
{
    MMRESULT wresult;
    lphWaveIn = &hWaveIn;     //wave handle
    lpwfIn = &pwfIn;          //wave format
    pwfIn.wFormatTag=WAVE_FORMAT_PCM;
    pwfIn.nChannels=2;
    pwfIn.nSamplesPerSec=SAMPLES;
    pwfIn.nAvgBytesPerSec=SAMPLES*2*BITS/8;
    pwfIn.nBlockAlign=2*BITS/8;
    pwfIn.wBitsPerSample=BITS;
    pwfIn.cbSize = 0;
    wresult = waveInOpen(lphWaveIn,WAVE_MAPPER,lpwfIn,(DWORD) cbWaveInProc,(DWORD) 0,(DWORD) CALLBACK_FUNCTION | WAVE_ALLOWSYNC );
    hInData = GlobalAlloc(GMEM_MOVEABLE,BUFFERLENGTH*4);
    wavInBuffer = (short *)GlobalLock(hInData);
    hInHdr = GlobalAlloc(GMEM_MOVEABLE,sizeof(WAVEHDR));
    lpwih = (LPWAVEHDR)GlobalLock(hInHdr);
    lpwih->lpData = (LPSTR)wavInBuffer;
    lpwih->dwBufferLength=BUFFERLENGTH*4;
    lpwih->dwFlags=0;
    return (long)wresult;
}
//close the wave out device and free waveInBuffer
long waveCloseIn(void)
{
    MMRESULT wresult;
    wresult = waveInClose(hWaveIn);
    GlobalUnlock(hInData);
    hInData = GlobalFree(hInData);
    GlobalUnlock(hInHdr);
    hInHdr = GlobalFree(hInHdr);
    return (long)wresult;
}
//*********HIGHER LEVEL API***********
long FAR PASCAL PlayTrack()
{
    MMRESULT wresult;
    wresult=waveOutPrepareHeader(hWaveOut,lpwoh,sizeof(WAVEHDR));
    wresult+=waveOutWrite(hWaveOut,lpwoh,sizeof(WAVEHDR));
    return (long) wresult;
}
long FAR PASCAL RecordTrack()
{
    MMRESULT wresult;
    wresult=waveOutPrepareHeader(hWaveOut,lpwoh,sizeof(WAVEHDR));
    wresult+=waveInPrepareHeader(hWaveIn,lpwih,sizeof(WAVEHDR));
    wresult+=waveInAddBuffer(hWaveIn,lpwih,sizeof(WAVEHDR));
    wresult+=waveInStart(hWaveIn);
    wresult+=waveOutWrite(hWaveOut,lpwoh,sizeof(WAVEHDR));
    return (long) wresult;
}
long FAR PASCAL StopTracks()
{
    MMRESULT wresult;
    wresult = waveInStop(hWaveIn);
    wresult = waveOutReset(hWaveOut);
    wresult = waveOutUnprepareHeader(hWaveOut,lpwoh,sizeof(WAVEHDR));
    wresult = waveInReset(hWaveIn);
    wresult = waveInUnprepareHeader(hWaveIn,lpwih,sizeof(WAVEHDR));
    return (long) wresult;
}