www.pudn.com > VC写的MP3播放器源代码.zip > mci_obuf.cpp


/////////////////////////////////////////////////////////////////////////////// 
// File: mci_obuf.cpp                  
// Author        :                          
// Comments    :                          
// Changings   :18-01-1999  by MCO 
//                                                                
/////////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "mci_obuf.h" 
 
 
BOOL	gTEST = FALSE; 
 
HANDLE MCIbuffer::m_hEvent; 
 
//#pragma argsused 
void CALLBACK MCICallBack(HWAVEOUT hwo, UINT uMsg, 
                         DWORD dwInstance, 
                         DWORD dwParam1, 
                         DWORD dwParam2) 
{ 
    switch(uMsg) 
    { 
        case WOM_DONE: 
        { 
            LPWAVEHDR lpWaveHdr = (LPWAVEHDR) dwParam1; 
            waveOutUnprepareHeader(hwo, lpWaveHdr, sizeof(WAVEHDR)); 
            SetEvent(MCIbuffer::m_hEvent); 
 
        } 
        break; 
    } 
} 
 
BOOL MCIbuffer::InitBuffer(CMpAudioFile* pHdr) 
{ 
	channels  = 2; 
    data_size = channels * BUFFERSIZE; 
     
    if (pHdr->GetVersion() == MPEG2_LSF) 
       data_size >>= 1; 
     
    if (pHdr->GetLayer() == 1) 
       data_size /= 3; 
     
    hdr_size      = sizeof(WAVEHDR); 
    lpwavehdr_arr = new LPWAVEHDR[3]; 
    //phwo          = &pHdr->phwo; 
    fillup        = 0; 
     
    lpwf = (tWAVEFORMATEX *) new WAVEFORMATEX; 
     
    lpwf->wBitsPerSample  = 16;  // No 8-bit support yet 
    lpwf->wFormatTag      = WAVE_FORMAT_PCM; 
    lpwf->nChannels       = (WORD) channels; 
    lpwf->nSamplesPerSec  = (DWORD) pHdr->GetFreq(); 
    lpwf->nAvgBytesPerSec = (DWORD) channels * 
                            pHdr->GetFreq() << 1; 
    lpwf->nBlockAlign     = (WORD) (channels << 1); 
    lpwf->cbSize          = 0; 
     
    if (waveOutOpen(&m_hWaveOut, WAVE_MAPPER, (const tWAVEFORMATEX *) lpwf, 
       (DWORD) MCICallBack, NULL, 
    WAVE_ALLOWSYNC | CALLBACK_FUNCTION) 
        != MMSYSERR_NOERROR) 
    { 
        MessageBox(0, "Could not open wave device.", 
        "Audio playback error", MB_ICONSTOP | MB_OK); 
		gTEST = TRUE; 
    } 
     
    buffer_count = 0; 
     
    DWORD i; 
     
    for(i=0; i<3; i++) { 
        lpwavehdr_arr[i] = (LPWAVEHDR) new WAVEHDR; 
         
        LPWAVEHDR temp = lpwavehdr_arr[i]; 
         
        if(!temp) return 0; 
         
        temp->lpData = (LPSTR) new char[data_size]; 
         
        if(!temp->lpData) return 0; 
        temp->dwBufferLength  = data_size; 
        temp->dwBytesRecorded = 0; 
        temp->dwUser          = 0;  // If played, dwUser = 1 
        temp->dwLoops         = 0; 
        temp->dwFlags         = NULL; 
    } 
     
    for(i=0; istream->GetVersion() == MPEG2_LSF) 
       data_size >>= 1; 
     
    if (maplay_args->stream->GetLayer() == 1) 
       data_size /= 3; 
     
    hdr_size      = sizeof(WAVEHDR); 
    lpwavehdr_arr = new LPWAVEHDR[3]; 
    //phwo          = maplay_args->phwo; 
    fillup        = 0; 
     
    lpwf = (tWAVEFORMATEX *) new WAVEFORMATEX; 
     
    lpwf->wBitsPerSample  = 16;  // No 8-bit support yet 
    lpwf->wFormatTag      = WAVE_FORMAT_PCM; 
    lpwf->nChannels       = (WORD) channels; 
    lpwf->nSamplesPerSec  = (DWORD) maplay_args->stream->GetFreq(); 
    lpwf->nAvgBytesPerSec = (DWORD) channels * 
                            maplay_args->stream->GetFreq() << 1; 
    lpwf->nBlockAlign     = (WORD) (channels << 1); 
    lpwf->cbSize          = 0; 
     
    if (waveOutOpen(&m_hWaveOut, WAVE_MAPPER, (const tWAVEFORMATEX *) lpwf, 
       (DWORD) MCICallBack, NULL, 
    WAVE_ALLOWSYNC | CALLBACK_FUNCTION) 
        != MMSYSERR_NOERROR) 
    { 
 
            MessageBox(maplay_args->hWnd, "Could not open wave device.", 
            "Audio playback error", MB_ICONSTOP | MB_OK); 
            return; 
    } 
     
    buffer_count = 0; 
     
    DWORD i; 
     
    for(i=0; i<3; i++) { 
        lpwavehdr_arr[i] = (LPWAVEHDR) new WAVEHDR; 
         
        LPWAVEHDR temp = lpwavehdr_arr[i]; 
         
        if(!temp) return; 
         
        temp->lpData = (LPSTR) new char[data_size]; 
         
        if(!temp->lpData) return; 
        temp->dwBufferLength  = data_size; 
        temp->dwBytesRecorded = 0; 
        temp->dwUser          = 0;  // If played, dwUser = 1 
        temp->dwLoops         = 0; 
        temp->dwFlags         = NULL; 
    } 
     
    for(i=0; ilpData; 
     
    temp[bufferp[channel]]   = (char) (value & 0xff); 
    temp[bufferp[channel]+1] = (char) (value >> 8); 
     
    bufferp[channel] += channels << 1; 
 
	 
	 
	return; 
} 
 
//#pragma argsused 
void MCIbuffer::write_buffer(int& fd) 
{ 
    // Actually write only when buffer is actually full. 
     
	//if ((++buffer_count & 0x1f) == 0)  
	if ((++buffer_count % 6) == 0)  
	{ 
		lpwavehdr_arr[2]->dwBufferLength = fd*2; 
		lpwavehdr_arr[0]->dwBufferLength = fd*2; 
		fd = 0; 
	 
         
        buffer_count = 0; 
         
        // Wait for 2 completed headers 
        if (fillup > 1)  
		{ 
 
    	    waveOutPrepareHeader(m_hWaveOut, lpwavehdr_arr[2], hdr_size); 
		    waveOutWrite(m_hWaveOut, lpwavehdr_arr[2], hdr_size); 
     
            lpwavehdr_arr[2]->dwUser = 1; 
             
            wave_swap(); 
             
            if (lpwavehdr_arr[2]->dwUser) 
			{ 
                WaitForSingleObject(m_hEvent, 10000); 
            } 
 
        }  
		else  
		{ 
            if (++fillup == 2)  
			{ 
                 
			    waveOutPrepareHeader(m_hWaveOut, lpwavehdr_arr[0], hdr_size); 
			    waveOutWrite(m_hWaveOut, lpwavehdr_arr[0], hdr_size); 
                 
                lpwavehdr_arr[0]->dwUser = 1; 
                 
                wave_swap(); 
    		    waveOutPrepareHeader(m_hWaveOut, lpwavehdr_arr[0], hdr_size); 
			    waveOutWrite(m_hWaveOut, lpwavehdr_arr[0], hdr_size); 
     
                lpwavehdr_arr[0]->dwUser = 1; 
 
                 
            } else  
			{ 
               wave_swap(); 
            } 
        } 
         
        for(DWORD i=0; idwUser) && (i < 2)) 
           WaitForSingleObject(m_hEvent, 10000); 
         
        temp->dwUser = 0; 
         
        for(unsigned int j=0; jlpData[j] = (char) 0; 
    } 
     
    //   waveOutReset(m_hWaveOut); 
     
    // Reset buffer pointers 
    for(i=0; ilpData; 
				//m_pDlg->m_tracer.SetPick(*p -32768); 
 
            // Header has been written. 
            lpwavehdr_arr[0]->dwUser = 1; 
        } 
         
        if (buffer_count)  
		{ 
             
            // Write the last wave header (probably not be written due to buffer 
            // size increase.) 
             
            for(unsigned int i = bufferp[channels-1]; i < data_size; i++) 
               lpwavehdr_arr[2]->lpData[i] = (char) 0; 
 
            if(!gTEST) 
            { 
             
                waveOutPrepareHeader(m_hWaveOut, lpwavehdr_arr[2], hdr_size); 
                waveOutWrite(m_hWaveOut, lpwavehdr_arr[2], hdr_size); 
            } 
            // Header has been written. 
            lpwavehdr_arr[2]->dwUser = 1; 
            wave_swap(); 
        } 
    } 
     
    // Unprepare and free the header memory. 
    for (int j=2; j>=0; j--) { 
        if (lpwavehdr_arr[j]->dwUser && !user_stop) 
           WaitForSingleObject(m_hEvent, 10000); 
         
        delete [] lpwavehdr_arr[j]->lpData; 
        delete lpwavehdr_arr[j]; 
    } 
     
    delete [] lpwavehdr_arr; 
    delete lpwf; 
	if(!gTEST) 
	{ 
 
		while(waveOutClose(m_hWaveOut) == WAVERR_STILLPLAYING) 
			 Sleep(SLEEPTIME); 
	}     
    CloseHandle(m_hEvent); 
     
    return; 
}