コード例 #1
0
ファイル: hxaudevds.cpp プロジェクト: muromec/qtopia-ezx
HX_RESULT CHXAudioDeviceDS::_DoOpen(const HXAudioFormat* pFormat)
{
    HX_RESULT theErr = HXR_FAIL;

    if(!m_hwnd || !m_hSoundDll)
	return theErr;

    // close open resources
    InternalClose() ;

    /* Get the IDirectSound interface */
    HXBOOL bUsingDS8 = TRUE;
    FPDIRECTSOUNDCREATE fpCreateDS = (FPDIRECTSOUNDCREATE) ::GetProcAddress(m_hSoundDll, TEXT("DirectSoundCreate8") );
    if(!fpCreateDS)
    {
	bUsingDS8 = FALSE;
	fpCreateDS = (FPDIRECTSOUNDCREATE) ::GetProcAddress(m_hSoundDll, TEXT("DirectSoundCreate"));
	if(!fpCreateDS)
	    return theErr;
    }

    theErr = fpCreateDS(NULL, &m_pDSDev, NULL);
    if (FAILED(theErr))
	return theErr;

    /* set the cooperative level. Because we want control over the format of the
       primary buffer (16 bit, multichannel!), we need DSSCL_PRIORITY. */
    m_pDSDev->SetCooperativeLevel(m_hwnd, DSSCL_PRIORITY );

    /* set the format of the primary buffer. This will fail on WDM systems (because
       the kernel mixer termines the primary buffer format), but is important on
       non-WDM systems.
    
       This might change the m_WaveFormat structure from a WAVE_FORMAT_EXTENSIBLE
       to a WAVEFORMATEX.

       Ignore the result.
    */
    SetPrimaryBufferFormat() ;

    /* Now open a secondary buffer. */

    DSBUFFERDESC bufferDesc;
    ::memset(&bufferDesc, 0, sizeof(DSBUFFERDESC));

    bufferDesc.dwSize	   = sizeof(DSBUFFERDESC);
    bufferDesc.lpwfxFormat = m_pWaveFormat;

    // Manipulate the buffer size so that is is an exact multiple of the block size.
    // This will ensure that our write positions on the buffer are the same in every loop.
    // We need to do this so that we have fixed playback notification positions marking the end each write block.
    m_nBlocksPerBuffer = (m_pWaveFormat->nAvgBytesPerSec*BUFFER_TIME)/pFormat->uMaxBlockSize;
    m_ulTotalBuffer = pFormat->uMaxBlockSize*m_nBlocksPerBuffer;
    m_ulLoopTime = (double)m_ulTotalBuffer / (double)m_pWaveFormat->nAvgBytesPerSec;

    bufferDesc.dwBufferBytes = m_ulTotalBuffer ;
    bufferDesc.dwFlags	=
		      DSBCAPS_CTRLVOLUME | // so we can control the volume
		      DSBCAPS_GETCURRENTPOSITION2 | // finer position reports
		      DSBCAPS_CTRLPOSITIONNOTIFY | // have them reported here
		      DSBCAPS_GLOBALFOCUS | // take control!
		      DSBCAPS_STICKYFOCUS |
#ifdef HELIX_FEATURE_AUDIO_DEVICE_HOOKS
		      (bUsingDS8 && m_pWaveFormat->nChannels <= 2 && !m_bOpaqueFormat ? DSBCAPS_CTRLFX : 0);
#else
		      0;
#endif

    /* Again, try with WAVE_FORMAT_EXTENSIBLE first, but only if multichannel. */

    theErr = !DS_OK ;
    if (m_pWaveFormat->nChannels > 2 || m_bOpaqueFormat)
    {
	if(!m_bOpaqueFormat)
	    m_pWaveFormat->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL);
    }

    if (theErr != DS_OK && !m_bOpaqueFormat)
    {
	/* and if that fails, try WAVEFORMATEX */
	m_pWaveFormat->wFormatTag = WAVE_FORMAT_PCM;
	theErr = m_pDSDev->CreateSoundBuffer(&bufferDesc, &m_pSecondaryBuffer, NULL);
    }

    /* call it a day and count our blessings. */
    switch (theErr)
    {
	case DS_OK: 
	    theErr = HXR_OK;
	    break;
	case DSERR_OUTOFMEMORY:
	    theErr = HXR_OUTOFMEMORY;
	    break;
	default:
	    theErr = HXR_FAIL;
	    break;
    }

    if (SUCCEEDED(theErr) && m_pSecondaryBuffer)
    {
	m_eState = E_DEV_OPENED;

	KillThreadAndEvent();

	SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);

	// Create the event to be signalled on playback position notifications and the thread to wait for those events to be signalled.
	m_hDSNotifyEvent = CreateEvent(NULL, TRUE, FALSE, kDSWaitEvent);

	// now set the notification positions for direct sound playback.
	IDirectSoundNotify* pNotify = NULL;
	m_pSecondaryBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&pNotify);
	if(pNotify && m_hDSNotifyEvent)
	{
	    DSBPOSITIONNOTIFY* aPositionNotify = new DSBPOSITIONNOTIFY[m_nBlocksPerBuffer];
	    if(aPositionNotify)
	    {
		for(int i = 0; i < m_nBlocksPerBuffer; i++)
		{
		    aPositionNotify[i].dwOffset = i * pFormat->uMaxBlockSize;
		    aPositionNotify[i].hEventNotify = m_hDSNotifyEvent;
		}
	    }
	    pNotify->SetNotificationPositions(m_nBlocksPerBuffer, aPositionNotify);
	    delete[] aPositionNotify;
	    DWORD dwWaitThreadID(0);
	    m_hWaitThread = CreateThread(NULL, 0, EventThreadProc, (LPVOID)this, 0, &dwWaitThreadID);
            SetDebuggerThreadName(dwWaitThreadID, "DirectSound Audio Device Thread");
	    SetThreadPriority( m_hWaitThread, THREAD_PRIORITY_HIGHEST );
	}
	HX_RELEASE(pNotify);

	m_pSecondaryBuffer->SetVolume(DSBVOLUME_MAX);
	m_pSecondaryBuffer->SetCurrentPosition(0);

        // detect whether we are playing remotely(via Remote Desktop)
        // disable audio device hook if it is to avoid poor audio quality
        int bRemoteSession = GetSystemMetrics(SM_REMOTESESSION);
	if(!bRemoteSession && bUsingDS8 && m_pWaveFormat->nChannels <= 2 && !m_bOpaqueFormat)
	{
	    LoadDirectSoundFilter();
	}
    }

    m_ulCurrPlayTime = 0;
	m_ulCurrLoopTime = 0;
    m_ulLoops = 0;

    // Setup converter to convert from samples/sec to milliseconds
    m_TSConverter.SetBase(m_pWaveFormat->nSamplesPerSec, 1000);

    return theErr;
}
コード例 #2
0
//-----------------------------------------------------------------------------
// Name: CSoundManager::CreateStreaming()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CSoundManager::CreateStreaming( CStreamingSound** ppStreamingSound,
						                LPTSTR strWaveFileName,
						                DWORD dwCreationFlags,
						                GUID guid3DAlgorithm,
						                DWORD dwNotifyCount,
						                DWORD dwNotifySize,
						                HANDLE hNotifyEvent )
{
	HRESULT hr;

	if( m_pDS == NULL )
		return CO_E_NOTINITIALIZED;
	if( strWaveFileName == NULL || ppStreamingSound == NULL || hNotifyEvent == NULL )
		return E_INVALIDARG;

	IDirectSoundBuffer* pDSBuffer      = NULL;
	DWORD               dwDSBufferSize = NULL;
	CWaveFile*          pWaveFile      = NULL;
	DSBPOSITIONNOTIFY*  aPosNotify     = NULL;
	IDirectSoundNotify* pDSNotify      = NULL;

	pWaveFile = new CWaveFile();
	if( pWaveFile == NULL )
		return E_OUTOFMEMORY;
	pWaveFile->Open( strWaveFileName, NULL, WAVEFILE_READ );

	// Figure out how big the DirectSound buffer should be
	dwDSBufferSize = dwNotifySize * dwNotifyCount;

	// Set up the direct sound buffer.  Request the NOTIFY flag, so
	// that we are notified as the sound buffer plays.  Note, that using this flag
	// may limit the amount of hardware acceleration that can occur.
	DSBUFFERDESC dsbd;
	ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
	dsbd.dwSize          = sizeof(DSBUFFERDESC);
	dsbd.dwFlags         = dwCreationFlags |
						   DSBCAPS_CTRLPOSITIONNOTIFY |
						   DSBCAPS_GETCURRENTPOSITION2;
	dsbd.dwBufferBytes   = dwDSBufferSize;
	dsbd.guid3DAlgorithm = guid3DAlgorithm;
	dsbd.lpwfxFormat     = pWaveFile->m_pwfx;

	if( FAILED( hr = m_pDS->CreateSoundBuffer( &dsbd, &pDSBuffer, NULL ) ) )
	{
		// If wave format isn't then it will return
		// either DSERR_BADFORMAT or E_INVALIDARG
		if( hr == DSERR_BADFORMAT || hr == E_INVALIDARG )
			return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );

		return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
	}

	// Create the notification events, so that we know when to fill
	// the buffer as the sound plays.
	if( FAILED( hr = pDSBuffer->QueryInterface( IID_IDirectSoundNotify,
						                        (VOID**)&pDSNotify ) ) )
	{
		SAFE_DELETE_ARRAY( aPosNotify );
		return DXTRACE_ERR( TEXT("QueryInterface"), hr );
	}

	aPosNotify = new DSBPOSITIONNOTIFY[ dwNotifyCount ];
	if( aPosNotify == NULL )
		return E_OUTOFMEMORY;

	for( DWORD i = 0; i < dwNotifyCount; i++ )
	{
		aPosNotify[i].dwOffset     = (dwNotifySize * i) + dwNotifySize - 1;
		aPosNotify[i].hEventNotify = hNotifyEvent;
	}

	// Tell DirectSound when to notify us. The notification will come in the from
	// of signaled events that are handled in WinMain()
	if( FAILED( hr = pDSNotify->SetNotificationPositions( dwNotifyCount,
						                                  aPosNotify ) ) )
	{
		SAFE_RELEASE( pDSNotify );
		SAFE_DELETE_ARRAY( aPosNotify );
		return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr );
	}

	SAFE_RELEASE( pDSNotify );
	SAFE_DELETE_ARRAY( aPosNotify );

	// Create the sound
	*ppStreamingSound = new CStreamingSound( pDSBuffer, dwDSBufferSize, pWaveFile, dwNotifySize );

	return S_OK;
}
コード例 #3
0
ファイル: WaveCapture.cpp プロジェクト: thenfour/Volumizer
/*
    nInterval is in SECONDS.  The buffer we create is 3 times the interval,
    so we make three notifications that will be placed at every interval.

    pProc will be called at approximately the interval specified.
*/
HRESULT WaveCapture::Initialize(int nDevice, WAVEFORMATEX* pFormat, WAVECAPTUREPROC pProc, PVOID pUser, int nInterval)
{
    DSCCAPS dsc;
    DSCBUFFERDESC1 dscbDesc;
    HRESULT hr;
    DSBPOSITIONNOTIFY NotifyPositions[3];
    IDirectSoundNotify* pdsn;

    this->Uninitialize();

    this->pProc = pProc;
    this->pUser = pUser;
    this->nInterval = nInterval;

    // Validation.
    if(pFormat->wFormatTag != WAVE_FORMAT_PCM)
    {
        return E_FAIL;
    }

    // Copy the wave format for our own purposes.
    memcpy(&this->Format, pFormat, sizeof(WAVEFORMATEX));

    m_iDevice = nDevice;
    memset(&m_Device, 0, sizeof(GUID));
    DirectSoundCaptureEnumerate(WaveCapture::DSEnumCallback, this);

    // Create DirectSoundCapture object.
    if(FAILED(hr = DirectSoundCaptureCreate(&m_Device, &this->pdsc, NULL)))
    {
        return E_FAIL;
    }

    /*
        Here is where we should check the capabilities of the sound card against
        the format that was passed in.
    */
    dsc.dwSize = sizeof(DSCCAPS);
    if(FAILED(hr = this->pdsc->GetCaps(&dsc)))
    {
        SAFE_RELEASE(this->pdsc);
        return E_FAIL;
    }

    /*
        Create the capture buffer.
    */
    dscbDesc.dwSize = sizeof(dscbDesc);
    dscbDesc.dwFlags = DSCBCAPS_WAVEMAPPED;
    dscbDesc.dwBufferBytes = (pFormat->nAvgBytesPerSec * nInterval) * 3;
    dscbDesc.dwReserved = 0;
    dscbDesc.lpwfxFormat = &this->Format;

    if(FAILED(hr = this->pdsc->CreateCaptureBuffer((DSCBUFFERDESC*)&dscbDesc, &this->pdsb, NULL)))
    {
        SAFE_RELEASE(this->pdsc);
        return E_FAIL;
    }

    /*
        Create the notifications
    */
    this->hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
    this->hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
    this->hEvents[2] = CreateEvent(NULL, FALSE, FALSE, NULL);
    this->hEvents[3] = CreateEvent(NULL, FALSE, FALSE, NULL);

    NotifyPositions[0].dwOffset = 0;
    NotifyPositions[0].hEventNotify = this->hEvents[0];

    NotifyPositions[1].dwOffset = (this->Format.nAvgBytesPerSec * nInterval);
    NotifyPositions[1].hEventNotify = this->hEvents[1];

    NotifyPositions[2].dwOffset = (this->Format.nAvgBytesPerSec * nInterval) * 2;
    NotifyPositions[2].hEventNotify = this->hEvents[2];

    if(FAILED(hr = this->pdsb->QueryInterface(IID_IDirectSoundNotify, (PVOID*)&pdsn)))
    {
        SAFE_RELEASE(this->pdsb);
        SAFE_RELEASE(this->pdsc);
        return E_FAIL;
    }

    if(FAILED(hr = pdsn->SetNotificationPositions(3, NotifyPositions)))
    {
        SAFE_RELEASE(pdsn);
        SAFE_RELEASE(this->pdsb);
        SAFE_RELEASE(this->pdsc);
        return E_FAIL;
    }

    SAFE_RELEASE(pdsn);

    /*
        Create our own buffer so when we pass data to pProc, the data is ALWAYS
        contiguous.
    */
    this->nBufferSize = (pFormat->nAvgBytesPerSec * nInterval) * 3;
    this->pBuffer = (PBYTE)malloc(this->nBufferSize);

    /*
        Initialize our own information.
    */
    this->dwLastPosition = 0;
    this->nPassesLeft = 1;

    /*
        Now create our recording thread so life can continue.
    */
    UINT dwThreadId;
	this->hThread = (HANDLE)_beginthreadex(
        0, 0, WaveCapture::RecordingThread, this, 0, &dwThreadId);

    return S_OK;
}