⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winaudio.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// we want MS if we can get them	mmTime.wType = TIME_MS;	MMRESULT res = waveOutGetPosition(m_hWave, &mmTime, sizeof(MMTIME));	if (MMSYSERR_NOERROR == res)	{		// We must check the output format and convert to MS if possible		switch (mmTime.wType)		{			case TIME_MS:			{				ulDeviceTime = mmTime.u.ms;#if defined(_WIN32)				ULONG32 BitsPerSample = (pWFmt->nChannels * pWFmt->wBitsPerSample);#elif _WIN16				ULONG32 BitsPerSample = (pWFmt->nAvgBytesPerSec * 8 / pWFmt->nSamplesPerSec);#endif				ULONG32 BitsPerSecond = (BitsPerSample * pWFmt->nSamplesPerSec);				ulDeviceBytesPlayed = (mmTime.u.ms * BitsPerSecond) / 8000;			}			break;			case TIME_SAMPLES:			{				// Convert samples to MS				ulDeviceSamplesPlayed = mmTime.u.sample;				if (m_ulLastDeviceSamplesPlayed > ulDeviceSamplesPlayed &&				    ((m_ulLastDeviceSamplesPlayed - ulDeviceSamplesPlayed) > MAX_TIMESTAMP_GAP))				{				    m_ulDevPosRollOver++;				} 				m_ulLastDeviceSamplesPlayed = ulDeviceSamplesPlayed;				m_llDeviceSamplesPlayed = (INT64)ulDeviceSamplesPlayed + (INT64)m_ulDevPosRollOver * (INT64)MAX_UINT32;				ulDeviceTime = (ULONG32)(((float)m_llDeviceSamplesPlayed/(float)pWFmt->nSamplesPerSec)*1000.f);#if defined(_WIN32)				ULONG32 BitsPerSample = (pWFmt->nChannels * pWFmt->wBitsPerSample);#elif _WIN16				ULONG32 BitsPerSample = (pWFmt->nAvgBytesPerSec * 8 / pWFmt->nSamplesPerSec);#endif				ulDeviceBytesPlayed = (ULONG32)(mmTime.u.sample * 8.0f) / BitsPerSample;			}			break;			case TIME_BYTES:			{				// Convert Bytes to MS				ulDeviceBytesPlayed = mmTime.u.cb;				if (m_ulLastDeviceBytesPlayed > ulDeviceBytesPlayed &&				    ((m_ulLastDeviceBytesPlayed - ulDeviceBytesPlayed) > MAX_TIMESTAMP_GAP))				{				    m_ulDevPosRollOver++;				}				m_ulLastDeviceBytesPlayed = ulDeviceBytesPlayed;				m_llDeviceBytesPlayed = (INT64)ulDeviceBytesPlayed + (INT64)m_ulDevPosRollOver * (INT64)MAX_UINT32;//{FILE* f1 = ::fopen("c:\\audio.txt", "a+"); ::fprintf(f1, "ulDeviceBytesPlayed: %lu\n", ulDeviceBytesPlayed);::fclose(f1);}#if defined(_WIN32)				ULONG32 BitsPerSample = (pWFmt->nChannels * pWFmt->wBitsPerSample);#elif _WIN16				ULONG32 BitsPerSample = (pWFmt->nAvgBytesPerSec * 8 / pWFmt->nSamplesPerSec);#endif				ULONG32 BitsPerSecond = (BitsPerSample * pWFmt->nSamplesPerSec);				ulDeviceTime = (ULONG32)((m_llDeviceBytesPlayed * 8000)/(INT64)BitsPerSecond);			}			break;		}		// ?? ulCurrentTime = ulDeviceTime + m_StreamTimeOffset + m_CorrectionOffset;		ulCurrentTime = m_ulCurrentTime = ulDeviceTime;	}	else	{		ulCurrentTime = m_ulCurrentTime = 0;	}	//{FILE* f1 = ::fopen("c:\\audio.txt", "a+"); ::fprintf(f1, "%lu\t%lu\n", HX_GET_TICKCOUNT(), m_ulCurrentTime);::fclose(f1);}	return HXR_OK;}/************************************************************************ *  Method: *              CAudioOutWindows::WaveOutProc *      Purpose: *              This static member function is called when the wave  *              device is finished playing its audio buffer.  We use  *              it to tell audio services that we're ready for more. */#if defined(_WIN32)	LRESULT __declspec(dllexport) CALLBACK #else	LRESULT CALLBACK __export #endifCAudioOutWindows::WaveOutWndProc(HWND hWnd,	// handle of window				UINT uMsg,	// message identifier				WPARAM wParam,	// first message parameter				LPARAM lParam) 	// second message parameter){    DWORD dwParam1 = lParam;    CAudioOutWindows* pThis = 0;    if (uMsg == WM_NCCREATE)    {	CREATESTRUCT* lpCreate = 0;	// Set our this pointer, so our WndProc can find us again	lpCreate = (CREATESTRUCT FAR*) lParam;	pThis = (CAudioOutWindows*) lpCreate->lpCreateParams;	SetWindowLong(hWnd, OFFSET_THIS, (long) pThis);    }    else if (uMsg == WM_NCDESTROY)    {	// remove our this pointer so if somebody calls this function	// again after the window is gone (and the object is gone	// too) we don't try to call a method from the pointer	SetWindowLong(hWnd, OFFSET_THIS, 0L);    }    else    {	pThis = (CAudioOutWindows*) (LPHANDLE)GetWindowLong(hWnd, OFFSET_THIS);    }    if (!pThis)    {	goto exit;    }    switch (uMsg)    {	    case MM_WOM_DONE:		    HX_ASSERT(zm_bClosed || zm_pCurrentAudioDevice == pThis);		    if (!zm_bClosed && zm_pCurrentAudioDevice == pThis)		    {			    // Only do this on WOM_DONE, note there are other messages sent to this			    // callback function, like WOM_OPEN and WOM_CLOSE			    //DWORD dwTime1 = timeGetTime();			    //OutputDebugString("START:(uMsg == MM_WOM_DONE) in WaveOutThreadProc\r\n");			    pThis->m_pMutex->Lock();			    if (zm_bClosed)			    {				pThis->m_pMutex->Unlock();				goto exit;			    }			    WAVEHDR*		pWAVEHDR;			    CWaveHeader*	pWaveHeader;			    			    pWAVEHDR = (WAVEHDR*)dwParam1;			    pWaveHeader = (CWaveHeader*)pWAVEHDR->dwUser;			    /* We may have already removed it from the queue			     * while checking for _NumberOfBlocksRemainingToPlay			     */			    if ((pWAVEHDR->dwFlags & WHDR_DONE) &&                                !pThis->m_UsedBuffersList.IsEmpty() &&				pThis->m_UsedBuffersList.GetHead() == (void*) pWaveHeader)			    {				// put it back in the queue				pWaveHeader->m_bAvail	= TRUE;				pThis->m_rAvailBuffers.EnQueuePtr(pWaveHeader);				/* This is assuming that we get WOM_DONEs sequentially				 * There seems to be a bug in WIN16 where it may return				 * WOM_DONEs out of order. Need to be fixed for that				 * XXX Rahul				 */				pThis->m_UsedBuffersList.RemoveHead();			    }			    pThis->m_pMutex->Unlock();			    if (pThis &&				!pThis->m_bResetting)			    {				//  Call the base class's  OnTimeSync to let it know that we're done playing				//  the current chunk of audio				//OutputDebugString("BEFORE:pThis->OnTimeSync()\r\n");				pThis->OnTimeSync();			    }		    }		    break;	    case MM_WOM_OPEN:		    break;			       	    	    case MM_WOM_CLOSE:   			    break;		    	    default:		    break;	    }    if (uMsg == zm_uDestroyMessage)    {	LRESULT result = (LRESULT)DestroyWindow(hWnd);	// free the memory used by this class now that our window is destroyed	UnregisterClass(WND_CLASS, g_hInstance);	return result;    }exit:    return ( DefWindowProc(hWnd, uMsg, wParam, lParam) );    }UINT16	CAudioOutWindows::_NumberOfBlocksRemainingToPlay(void){    m_pMutex->Lock();    UINT16 unRemaining = m_UsedBuffersList.GetCount();    /* There may be some buffers for which we have not receoved WOM_DONEs     * but they have already been played     */    if (unRemaining > 0)    {	LISTPOSITION ndxLastUsed = NULL;	LISTPOSITION ndxUsed = m_UsedBuffersList.GetHeadPosition();	while (ndxUsed != NULL)	{	    ndxLastUsed	= ndxUsed;	    CWaveHeader* pWaveHeader = 		    (CWaveHeader*) m_UsedBuffersList.GetNext(ndxUsed);	    if (pWaveHeader->m_WAVEHDR.dwFlags & WHDR_DONE)	    {		if (unRemaining > 0)		    unRemaining--;		// put it back in the queue		pWaveHeader->m_bAvail	= TRUE;		m_rAvailBuffers.EnQueuePtr(pWaveHeader);		m_UsedBuffersList.RemoveAt(ndxLastUsed);	    }	    else	    {		/* We assume that subsequent blocks are also not done playing */		break;	    }	}    }    m_pMutex->Unlock();    return unRemaining;}#if defined(_WIN32) && !defined(_WINCE)voidCAudioOutWindows::CheckForVolumeSupport(){    zm_bMixerVolSupportChecked = TRUE;    if (!m_hWnd)    {	Register();    }    // if there is more than 1 mixer, we need to find out which is the current one    // we do this by determining the mixer being used by the current wave device    int startIndex = 0;    if (m_hWave != NULL && mixerGetNumDevs() > 1)    {	UINT nId = -1;   	if ((mixerGetID((HMIXEROBJ)m_hWave, &nId, MIXER_OBJECTF_HWAVEOUT) == MMSYSERR_NOERROR) && nId != -1)	{	    startIndex = nId;	}    }    for(UINT index = startIndex; index < mixerGetNumDevs(); index++)    {	if(mixerOpen(&m_hMixer, index, (DWORD)m_hWnd, 0, CALLBACK_WINDOW) 							== MMSYSERR_NOERROR)	{	    MIXERLINE mxLine;	    mxLine.cbStruct = sizeof(MIXERLINE);	    mxLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;	    if(mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxLine, 	       MIXER_GETLINEINFOF_COMPONENTTYPE | MIXER_OBJECTF_HMIXER) 						    == MMSYSERR_NOERROR)	    {		// use waveOutSetVolume for bad device(i.e. crystal audio)		if (zm_audioDevice == HXAUDIO_UNKNOWN && mxLine.Target.szPname)		{		    for (int i = 0; i < g_nBadDrivers; i++)		    {			if (_tcsstr(mxLine.Target.szPname, g_badDrivers[i]))			{			    zm_audioDevice = HXAUDIO_BADDEVICE;			    break;			}		    }		    if (zm_audioDevice == HXAUDIO_UNKNOWN)		    {			zm_audioDevice = HXAUDIO_GOODDEVICE;		    }		}		if (zm_audioDevice != HXAUDIO_BADDEVICE)		{		    MIXERCONTROL mxControl;		    mxControl.cbStruct = sizeof(MIXERCONTROL);		    MIXERLINECONTROLS mxLineControls;		    mxLineControls.cbStruct = sizeof(MIXERLINECONTROLS);		    mxLineControls.dwLineID = mxLine.dwLineID;		    mxLineControls.cControls = 1;		    mxLineControls.cbmxctrl = mxControl.cbStruct;		    mxLineControls.pamxctrl = &mxControl;		    mxLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME | 						   MIXERCONTROL_CONTROLF_UNIFORM;		    if(mixerGetLineControls((HMIXEROBJ)m_hMixer, &mxLineControls, 		       MIXER_GETLINECONTROLSF_ONEBYTYPE | MIXER_OBJECTF_HMIXER) 							    == MMSYSERR_NOERROR)		    {			if(mxLineControls.cControls)			{			    zm_bVolSupport = TRUE;			    zm_bMixerVolSupport = TRUE;			    m_VolumeControlDetails.cbStruct = 						sizeof(MIXERCONTROLDETAILS); 			    m_VolumeControlDetails.dwControlID = 						mxControl.dwControlID; 			    m_VolumeControlDetails.cChannels = 1; 			    m_VolumeControlDetails.cMultipleItems = 						mxControl.cMultipleItems; 			}		    }   		}	    }	    break;	}    }}#endif /*_WIN32*/HX_RESULTCAudioOutWindows::Register(){    WNDCLASS internalClass;//    OutputDebugString("BEFORE CALL TO:Register\r\n");    if (m_hWnd)    {	return HXR_OK;    }	//m_hInst = hInst;	m_hInst = g_hInstance;	if (!m_hInst)	{#ifdef _DEBUG	MessageBox(NULL, _T("Don't have a valid handle"), NULL, MB_OK);#endif 	return HXR_OUTOFMEMORY;	}	// XXXKM - let's see if we can get the class info first; added this additional	// check due to a strange problem when registering a class that seems to already	// be registered.  For some reason, under some circumstance, RegisterClass returns	// NULL and GetLastError returns 0x57 (invalid parameter), however the class	// is already registered	if (!::GetClassInfo(m_hInst, WND_CLASS, &internalClass))	{		//	First register our window class                                  		internalClass.style 	= 0;		internalClass.lpfnWndProc 	= CAudioOutWindows::WaveOutWndProc;		internalClass.cbClsExtra    = 0;		internalClass.cbWndExtra    = sizeof( this );		internalClass.hInstance     = m_hInst; // Use app's instance		internalClass.hIcon         = 0;		internalClass.hCursor       = 0;		internalClass.hbrBackground = 0;		internalClass.lpszMenuName  = NULL;		internalClass.lpszClassName = WND_CLASS;	#ifdef _WIN16		if (!RegisterClass( &internalClass ))	#else		if (!RegisterClass( &internalClass ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)	#endif /* _WIN16 */    		{	#ifdef _DEBUG		MessageBox(NULL, _T("Could Not register class"), NULL, MB_OK);	#endif		return(HXR_OUTOFMEMORY);		}		m_bClassRegistered = TRUE;	}//    OutputDebugString("BEFORE CALL TO:CreateWindow\r\n");    //	Now create an instance of the window	    m_hWnd = CreateWindow( WND_CLASS /*"AudioServicesInternal"*/, _T("Audio Services Internal Messages"), 	WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, m_hInst, this);#if defined(_WIN32)    m_ulOriginalThreadId = GetCurrentThreadId();#endif    if (!m_hWnd)    {#ifdef _DEBUG	MessageBox(NULL, _T("Could Not create messageWindow"), NULL, MB_OK);#endif	return HXR_OUTOFMEMORY;    }    return HXR_OK;}voidCAudioOutWindows::UnRegister(){//    OutputDebugString("BEFORE CALL TO:UnRegister\r\n");    // Ask the window to destroy itself    if (m_hWnd)     {#if defined(_WIN32)	if (m_ulOriginalThreadId == GetCurrentThreadId())	{	    SendMessage(m_hWnd, zm_uDestroyMessage, 0, 0);	}	else	{	    PostMessage(m_hWnd, zm_uDestroyMessage, 0, 0);	    Sleep(0);	}#else	SendMessage(m_hWnd, zm_uDestroyMessage, 0, 0);#endif	m_hWnd = NULL;    }/*    // Ask the window to destroy itself    if (m_hWnd && SendMessage(m_hWnd, zm_uDestroyMessage, 0, 0))     {	m_hWnd = NULL;    }    // free the memory used by this class now that our window is destroyed    UnregisterClass(WND_CLASS, g_hInstance);*/}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -