コード例 #1
0
int tdav_consumer_dsound_start(tmedia_consumer_t* self)
{
	tdav_consumer_dsound_t* dsound = (tdav_consumer_dsound_t*)self;

	tsk_size_t i;
	HRESULT hr;
	LPDIRECTSOUNDNOTIFY lpDSBNotify;
	DSBPOSITIONNOTIFY pPosNotify[TDAV_DSOUNS_CONSUMER_NOTIF_POS_COUNT] = {0};

	if(!dsound){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	if(!dsound->device || !dsound->primaryBuffer || !dsound->secondaryBuffer){
		TSK_DEBUG_ERROR("Consumer not prepared");
		return -2;
	}

	if(dsound->started){
		TSK_DEBUG_WARN("Consumer already started");
		return 0;
	}

	if((hr = IDirectSoundBuffer_QueryInterface(dsound->secondaryBuffer, &IID_IDirectSoundNotify, (LPVOID*)&lpDSBNotify)) != DS_OK){
		tdav_win32_print_error("IDirectSoundBuffer_QueryInterface", hr);
		return -3;
	}

	/* Events associated to notification points */
	for(i = 0; i<sizeof(dsound->notifEvents)/sizeof(HANDLE); i++){
		dsound->notifEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
		pPosNotify[i].dwOffset = ((dsound->bytes_per_notif * i) + dsound->bytes_per_notif) - 1;
		pPosNotify[i].hEventNotify = dsound->notifEvents[i];
	}
	if((hr = IDirectSoundNotify_SetNotificationPositions(lpDSBNotify, TDAV_DSOUNS_CONSUMER_NOTIF_POS_COUNT, pPosNotify)) != DS_OK){
		IDirectSoundNotify_Release(lpDSBNotify);
		tdav_win32_print_error("IDirectSoundBuffer_QueryInterface", hr);
		return -4;
	}
	
	if((hr = IDirectSoundNotify_Release(lpDSBNotify))){
		tdav_win32_print_error("IDirectSoundNotify_Release", hr);
	}
	
	/* start the reader thread */
	tsk_thread_create(&dsound->tid[0], __playback_thread, dsound);

	/* Start the buffer */
	if((hr = IDirectSoundBuffer_Play(dsound->secondaryBuffer,0, 0, DSBPLAY_LOOPING)) != DS_OK){
		tdav_win32_print_error("IDirectSoundNotify_Release", hr);
		return -5;
	}

	dsound->started = tsk_true;

	return 0;
}
コード例 #2
0
ファイル: dsound.c プロジェクト: ktabata/suika2
/*
 * セカンダリバッファを作成し、再生位置通知を有効にする
 */
static BOOL CreateSecondaryBuffers()
{
	DSBPOSITIONNOTIFY pn[4];
	DSBUFFERDESC dsbd;
	HRESULT hRet;
	int i;

	memset(&dsbd, 0, sizeof(DSBUFFERDESC));
	dsbd.dwSize = sizeof(DSBUFFERDESC);
	dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY |	 /* 再生位置通知を利用可能にする */
				   DSBCAPS_GETCURRENTPOSITION2 | /* GetCurrentPositon()で正確な再生位置を取得可能にする */
				   DSBCAPS_GLOBALFOCUS |         /* 非アクティブでも再生する */
				   DSBCAPS_CTRLVOLUME;           /* ボリュームを設定可能にする */
	dsbd.dwBufferBytes = BUF_BYTES;
	dsbd.lpwfxFormat = &wfPrimary;

	for(i=0; i<MIXER_STREAMS; i++)
	{
		// セカンダリバッファを作成する
		hRet = IDirectSound_CreateSoundBuffer(pDS, &dsbd, &pDSBuffer[i], NULL);
		if(hRet != DS_OK)
			return FALSE;

		// 再生位置通知を利用する準備を行う
		hRet = IDirectSoundBuffer_QueryInterface(pDSBuffer[i],
												 &IID_IDirectSoundNotify,
												 (VOID**)&pDSNotify[i]);
		if(hRet != S_OK)
			return FALSE;

		hNotifyEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
		if(hNotifyEvent[i] == NULL)
			return FALSE;

		// 通知位置を設定する
		pn[0].dwOffset = 0;
		pn[0].hEventNotify = hNotifyEvent[i];
		pn[1].dwOffset = AREA_BYTES;
		pn[1].hEventNotify = hNotifyEvent[i];
		pn[2].dwOffset = AREA_BYTES * 2;
		pn[2].hEventNotify = hNotifyEvent[i];
		pn[3].dwOffset = AREA_BYTES * 3;
		pn[3].hEventNotify = hNotifyEvent[i];
		hRet = IDirectSoundNotify_SetNotificationPositions(pDSNotify[i],
														   4,
														   pn);
		if(hRet != DS_OK)
			return FALSE;
    }

	InitializeCriticalSection(&StreamCritical);
	return TRUE;
}
コード例 #3
0
ファイル: SDL_dx5audio.c プロジェクト: bohwaz/ozex
static int CreateAudioEvent(_THIS)
{
	LPDIRECTSOUNDNOTIFY notify;
	DSBPOSITIONNOTIFY *notify_positions;
	int i, retval;
	HRESULT result;

	/* Default to fail on exit */
	retval = -1;
	notify = NULL;

	/* Query for the interface */
	result = IDirectSoundBuffer_QueryInterface(mixbuf,
			&IID_IDirectSoundNotify, (void *)&notify);
	if ( result != DS_OK ) {
		goto done;
	}

	/* Allocate the notify structures */
	notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS*
					sizeof(*notify_positions));
	if ( notify_positions == NULL ) {
		goto done;
	}

	/* Create the notify event */
	audio_event = CreateEvent(NULL, FALSE, FALSE, NULL);
	if ( audio_event == NULL ) {
		goto done;
	}

	/* Set up the notify structures */
	for ( i=0; i<NUM_BUFFERS; ++i ) {
		notify_positions[i].dwOffset = i*mixlen;
		notify_positions[i].hEventNotify = audio_event;
	}
	result = IDirectSoundNotify_SetNotificationPositions(notify,
					NUM_BUFFERS, notify_positions);
	if ( result == DS_OK ) {
		retval = 0;
	}
done:
	if ( notify != NULL ) {
		IDirectSoundNotify_Release(notify);
	}
	return(retval);
}
コード例 #4
0
static ALCboolean DSoundResetPlayback(ALCdevice *device)
{
    DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData;
    DSBUFFERDESC DSBDescription;
    WAVEFORMATEXTENSIBLE OutputType;
    DWORD speakers;
    HRESULT hr;

    memset(&OutputType, 0, sizeof(OutputType));

    if(data->Notifies)
        IDirectSoundNotify_Release(data->Notifies);
    data->Notifies = NULL;
    if(data->Buffer)
        IDirectSoundBuffer_Release(data->Buffer);
    data->Buffer = NULL;
    if(data->PrimaryBuffer != NULL)
        IDirectSoundBuffer_Release(data->PrimaryBuffer);
    data->PrimaryBuffer = NULL;

    switch(device->FmtType)
    {
        case DevFmtByte:
            device->FmtType = DevFmtUByte;
            break;
        case DevFmtFloat:
            if((device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
                break;
            /* fall-through */
        case DevFmtUShort:
            device->FmtType = DevFmtShort;
            break;
        case DevFmtUInt:
            device->FmtType = DevFmtInt;
            break;
        case DevFmtUByte:
        case DevFmtShort:
        case DevFmtInt:
            break;
    }

    hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers);
    if(SUCCEEDED(hr))
    {
        if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
        {
            speakers = DSSPEAKER_CONFIG(speakers);
            if(speakers == DSSPEAKER_MONO)
                device->FmtChans = DevFmtMono;
            else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
                device->FmtChans = DevFmtStereo;
            else if(speakers == DSSPEAKER_QUAD)
                device->FmtChans = DevFmtQuad;
            else if(speakers == DSSPEAKER_5POINT1)
                device->FmtChans = DevFmtX51;
            else if(speakers == DSSPEAKER_7POINT1)
                device->FmtChans = DevFmtX71;
            else
                ERR("Unknown system speaker config: 0x%lx\n", speakers);
        }

        switch(device->FmtChans)
        {
            case DevFmtMono:
                OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
                break;
            case DevFmtStereo:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT;
                break;
            case DevFmtQuad:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_BACK_LEFT |
                                           SPEAKER_BACK_RIGHT;
                break;
            case DevFmtX51:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_BACK_LEFT |
                                           SPEAKER_BACK_RIGHT;
                break;
            case DevFmtX51Side:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_SIDE_LEFT |
                                           SPEAKER_SIDE_RIGHT;
                break;
            case DevFmtX61:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_BACK_CENTER |
                                           SPEAKER_SIDE_LEFT |
                                           SPEAKER_SIDE_RIGHT;
                break;
            case DevFmtX71:
                OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_BACK_LEFT |
                                           SPEAKER_BACK_RIGHT |
                                           SPEAKER_SIDE_LEFT |
                                           SPEAKER_SIDE_RIGHT;
                break;
        }

retry_open:
        hr = S_OK;
        OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
        OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
        OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
        OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
        OutputType.Format.nSamplesPerSec = device->Frequency;
        OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign;
        OutputType.Format.cbSize = 0;
    }

    if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
    {
        OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
        OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
        OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
        if(device->FmtType == DevFmtFloat)
            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
        else
            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;

        if(data->PrimaryBuffer)
            IDirectSoundBuffer_Release(data->PrimaryBuffer);
        data->PrimaryBuffer = NULL;
    }
    else
    {
        if(SUCCEEDED(hr) && !data->PrimaryBuffer)
        {
            memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
            DSBDescription.dwSize=sizeof(DSBUFFERDESC);
            DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
            hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL);
        }
        if(SUCCEEDED(hr))
            hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format);
    }

    if(SUCCEEDED(hr))
    {
        if(device->NumUpdates > MAX_UPDATES)
        {
            device->UpdateSize = (device->UpdateSize*device->NumUpdates +
                                  MAX_UPDATES-1) / MAX_UPDATES;
            device->NumUpdates = MAX_UPDATES;
        }

        memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
        DSBDescription.dwSize=sizeof(DSBUFFERDESC);
        DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS;
        DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates *
                                     OutputType.Format.nBlockAlign;
        DSBDescription.lpwfxFormat=&OutputType.Format;
        hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL);
        if(FAILED(hr) && device->FmtType == DevFmtFloat)
        {
            device->FmtType = DevFmtShort;
            goto retry_open;
        }
    }

    if(SUCCEEDED(hr))
    {
        hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies);
        if(SUCCEEDED(hr))
        {
            DSBPOSITIONNOTIFY notifies[MAX_UPDATES];
            ALuint i;

            for(i = 0;i < device->NumUpdates;++i)
            {
                notifies[i].dwOffset = i * device->UpdateSize *
                                       OutputType.Format.nBlockAlign;
                notifies[i].hEventNotify = data->NotifyEvent;
            }
            if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK)
                hr = E_FAIL;
        }
    }

    if(FAILED(hr))
    {
        if(data->Notifies != NULL)
            IDirectSoundNotify_Release(data->Notifies);
        data->Notifies = NULL;
        if(data->Buffer != NULL)
            IDirectSoundBuffer_Release(data->Buffer);
        data->Buffer = NULL;
        if(data->PrimaryBuffer != NULL)
            IDirectSoundBuffer_Release(data->PrimaryBuffer);
        data->PrimaryBuffer = NULL;
        return ALC_FALSE;
    }

    ResetEvent(data->NotifyEvent);
    SetDefaultWFXChannelOrder(device);

    return ALC_TRUE;
}
コード例 #5
0
int DirectSoundDrv_PCM_Init(int * mixrate, int * numchannels, int * samplebits, void * initdata)
{
    HRESULT err;
    DSBUFFERDESC bufdesc;
    WAVEFORMATEX wfex;
    
    if (Initialised) {
        DirectSoundDrv_PCM_Shutdown();
    }
    
    err = DirectSoundCreate(0, &lpds, 0);
    if (FAILED( err )) {
        ErrorCode = DSErr_DirectSoundCreate;
        return DSErr_Error;
    }

    err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_SetCooperativeLevel;
        return DSErr_Error;
    }
    
    memset(&bufdesc, 0, sizeof(DSBUFFERDESC));
    bufdesc.dwSize = sizeof(DSBUFFERDESC);
    bufdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    
    err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_CreateSoundBuffer;
        return DSErr_Error;
    }
    
    memset(&wfex, 0, sizeof(WAVEFORMATEX));
    wfex.wFormatTag = WAVE_FORMAT_PCM;
    wfex.nChannels = *numchannels;
    wfex.nSamplesPerSec = *mixrate;
    wfex.wBitsPerSample = *samplebits;
    wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8;
    wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
    
    err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_SetFormat;
        return DSErr_Error;
    }
    
    bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE |
                      DSBCAPS_CTRLPOSITIONNOTIFY |
                      DSBCAPS_GETCURRENTPOSITION2;
    bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2;
    bufdesc.lpwfxFormat = &wfex;
    
    err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_SetFormatSecondary;
        return DSErr_Error;
    }
    
    err = IDirectSoundBuffer_QueryInterface(lpdsbsec, &IID_IDirectSoundNotify,
            (LPVOID *) &lpdsnotify);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_Notify;
        return DSErr_Error;
    }
    
    notifyPositions[0].dwOffset = 0;
    notifyPositions[0].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
    notifyPositions[1].dwOffset = bufdesc.dwBufferBytes / 2;
    notifyPositions[1].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
    notifyPositions[2].dwOffset = DSBPN_OFFSETSTOP;
    notifyPositions[2].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!notifyPositions[0].hEventNotify ||
        !notifyPositions[1].hEventNotify ||
        !notifyPositions[2].hEventNotify) {
        TeardownDSound(DS_OK);
        ErrorCode = DSErr_NotifyEvents;
        return DSErr_Error;
    }
    
    err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, 3, notifyPositions);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_SetNotificationPositions;
        return DSErr_Error;
    }
    
    err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING);
    if (FAILED( err )) {
        TeardownDSound(err);
        ErrorCode = DSErr_Play;
        return DSErr_Error;
    }
    
    mutex = CreateMutex(0, FALSE, 0);
    if (!mutex) {
        TeardownDSound(DS_OK);
        ErrorCode = DSErr_CreateMutex;
        return DSErr_Error;
    }
    
    Initialised = 1;
    
    fprintf(stderr, "DirectSound Init: yay\n");
    
	return DSErr_Ok;
}
コード例 #6
0
ファイル: drv_ds.c プロジェクト: OS2World/LIB-SDL-2014
static int DS_Init(void)
{
	DSBUFFERDESC soundBufferFormat;
	WAVEFORMATEX pcmwf;
	DSBPOSITIONNOTIFY positionNotifications[2];
	DWORD updateBufferThreadID;
	LPVOID p = NULL;

	if (DirectSoundCreate(NULL,&pSoundCard,NULL)!=DS_OK) {
		_mm_errno=MMERR_OPENING_AUDIO;
		return 1;
	}

	if (IDirectSound_SetCooperativeLevel
				(pSoundCard,GetForegroundWindow(),DSSCL_PRIORITY)!=DS_OK) {
		_mm_errno=MMERR_DS_PRIORITY;
		return 1;
	}

	memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC));
	soundBufferFormat.dwSize = sizeof(DSBUFFERDESC);
	soundBufferFormat.dwFlags = DSBCAPS_PRIMARYBUFFER;
	soundBufferFormat.dwBufferBytes = 0;
	soundBufferFormat.lpwfxFormat = NULL;

	if (IDirectSound_CreateSoundBuffer
				(pSoundCard,&soundBufferFormat,&pPrimarySoundBuffer,NULL)!=DS_OK) {
		_mm_errno=MMERR_DS_BUFFER;
		return 1;
	}

	memset(&pcmwf,0,sizeof(WAVEFORMATEX));
	pcmwf.wFormatTag     =(md_mode&DMODE_FLOAT)? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
	pcmwf.nChannels      =(md_mode&DMODE_STEREO)?2:1;
	pcmwf.nSamplesPerSec =md_mixfreq;
	pcmwf.wBitsPerSample =(md_mode&DMODE_FLOAT)?32:(md_mode&DMODE_16BITS)?16:8;
	pcmwf.nBlockAlign    =(pcmwf.wBitsPerSample * pcmwf.nChannels) / 8;
	pcmwf.nAvgBytesPerSec=pcmwf.nSamplesPerSec*pcmwf.nBlockAlign;

	if (IDirectSoundBuffer_SetFormat(pPrimarySoundBuffer,&pcmwf)!=DS_OK) {
		_mm_errno=MMERR_DS_FORMAT;
		return 1;
	}
	IDirectSoundBuffer_Play(pPrimarySoundBuffer,0,0,DSBPLAY_LOOPING);

	memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC));
	soundBufferFormat.dwSize	=sizeof(DSBUFFERDESC);
	soundBufferFormat.dwFlags	=controlflags|DSBCAPS_GETCURRENTPOSITION2 ;
	soundBufferFormat.dwBufferBytes =fragsize*UPDATES;
	soundBufferFormat.lpwfxFormat	=&pcmwf;

	if (IDirectSound_CreateSoundBuffer
				(pSoundCard,&soundBufferFormat,&pSoundBuffer,NULL)!=DS_OK) {
		_mm_errno=MMERR_DS_BUFFER;
		return 1;
	}

#ifdef __cplusplus
	IDirectSoundBuffer_QueryInterface(pSoundBuffer, IID_IDirectSoundNotify,&p);
#else
	IDirectSoundBuffer_QueryInterface(pSoundBuffer,&IID_IDirectSoundNotify,&p);
#endif
	if (!p) {
		_mm_errno=MMERR_DS_NOTIFY;
		return 1;
	}
	pSoundBufferNotify = (LPDIRECTSOUNDNOTIFY) p;

	notifyUpdateHandle=CreateEvent
				(NULL,FALSE,FALSE,"libmikmod DirectSound Driver positionNotify Event");
	if (!notifyUpdateHandle) {
		_mm_errno=MMERR_DS_EVENT;
		return 1;
	}

	updateBufferHandle=CreateThread
				(NULL,0,updateBufferProc,NULL,CREATE_SUSPENDED,&updateBufferThreadID);
	if (!updateBufferHandle) {
		_mm_errno=MMERR_DS_THREAD;
		return 1;
	}

	memset(positionNotifications,0,2*sizeof(DSBPOSITIONNOTIFY));
	positionNotifications[0].dwOffset    =0;
	positionNotifications[0].hEventNotify=notifyUpdateHandle;
	positionNotifications[1].dwOffset    =fragsize;
	positionNotifications[1].hEventNotify=notifyUpdateHandle;
	if (IDirectSoundNotify_SetNotificationPositions
				(pSoundBufferNotify,2,positionNotifications) != DS_OK) {
		_mm_errno=MMERR_DS_UPDATE;
		return 1;
	}

#if defined HAVE_SSE2
	/* this test only works on Windows XP or later */
	if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
		md_mode|=DMODE_SIMDMIXER;
	}
#endif
	return VC_Init();
}
コード例 #7
0
ファイル: capture.c プロジェクト: AmesianX/RosWine
static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
				LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
{
    HRESULT rc;
    DSCBCAPS dscbcaps;
    WAVEFORMATEX wfx;
    DWORD size,status;
    capture_state_t state;
    int i, ref;

    /* Private dsound.dll: Error: Invalid caps pointer */
    rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
       "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    /* Private dsound.dll: Error: Invalid caps pointer */
    dscbcaps.dwSize=0;
    rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
       "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    dscbcaps.dwSize=sizeof(dscbcaps);
    rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
    ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %08x\n", rc);
    if (rc==DS_OK && winetest_debug > 1) {
	trace("    Caps: size = %d flags=0x%08x buffer size=%d\n",
	    dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
    }

    /* Query the format size. Note that it may not match sizeof(wfx) */
    /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must
     * be non-NULL */
    rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should "
       "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    size=0;
    rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
    ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should "
       "have returned the needed size: rc=%08x, size=%d\n", rc,size);

    rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
    ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %08x\n", rc);
    if (rc==DS_OK && winetest_debug > 1) {
	trace("    Format: tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
	      wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
	      wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
    }

    /* Private dsound.dll: Error: Invalid status pointer */
    rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should "
       "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
    ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc);
    if (rc==DS_OK && winetest_debug > 1) {
	trace("    Status=0x%04x\n",status);
    }

    ZeroMemory(&state, sizeof(state));
    state.dscbo=dscbo;
    state.wfx=&wfx;
    state.buffer_size = dscbcaps.dwBufferBytes;
    for (i = 0; i < NOTIFICATIONS; i++)
	state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
    state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;

    rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,
                                                (void **)&(state.notify));
    ok((rc==DS_OK)&&(state.notify!=NULL),
       "IDirectSoundCaptureBuffer_QueryInterface() failed: %08x\n", rc);

    for (i = 0; i < NOTIFICATIONS; i++) {
	state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
	state.posnotify[i].hEventNotify = state.event[i];
    }

    rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,
                                                   state.posnotify);
    ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %08x\n", rc);

    ref=IDirectSoundNotify_Release(state.notify);
    ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have "
       "0\n",ref);

    if (record) {
	rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
	ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc);

	rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
	ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc);
	ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
           "GetStatus: bad status: %x\n",status);

	/* wait for the notifications */
	for (i = 0; i < (NOTIFICATIONS * 2); i++) {
	    rc=WaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,3000);
	    ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),
               "WaitForMultipleObjects failed: 0x%x\n",rc);
	    if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
		ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),
                   "Wrong notification: should be %d, got %d\n",
		    i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
	    }
	    if (!capture_buffer_service(&state))
		break;
	}

	rc=IDirectSoundCaptureBuffer_Stop(dscbo);
	ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc);
    }
}
コード例 #8
0
ファイル: dsoundout.c プロジェクト: wosigh/duke3d
/*
 * DSOUND_BeginBufferedPlayback
 * Spins off a thread that behaves somewhat like the SoundBlaster DMA ISR did.
 */
int DSOUND_BeginBufferedPlayback(char *BufferStart, int (*CallBackFunc)(int), int buffersize, int numdivisions)
{
	DWORD threadid;
	HRESULT hr;
	DSBPOSITIONNOTIFY *posns;
	int i;
	
	_DSOUND_CallBack = CallBackFunc;
	_DSOUND_MixBuffer = BufferStart;

	if (!lpDSBSecondary) return DSOUND_Error;

	if (isrthread) {
		DSOUND_StopPlayback();
	}
	
	isrfinish = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (!isrfinish) {
		DSOUND_SetErrorCode(DSOUND_FailedCreateFinishEvent);
		return DSOUND_Error;
	}
	
	isrthread = CreateThread(NULL, 0, isr, NULL, CREATE_SUSPENDED, &threadid);
	if (!isrthread) {
		DSOUND_SetErrorCode(DSOUND_FailedCreateThread);
		return DSOUND_Error;
	}

	hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)*numdivisions);
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}
	
	memset(hPosNotify, 0, sizeof(HANDLE)*numdivisions);
	for (i=0; i<numdivisions; i++) {
		hPosNotify[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (!hPosNotify[i]) {
			DSOUND_Shutdown();
			DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
			return DSOUND_Error;
		}
	}

	posns = (LPDSBPOSITIONNOTIFY)malloc(sizeof(DSBPOSITIONNOTIFY)*numdivisions);
	if (!posns) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	_DSOUND_BufferLength = buffersize/numdivisions;
	_DSOUND_NumBuffers   = numdivisions;
	for (i=0; i<numdivisions; i++) {
		posns[i].dwOffset = i*_DSOUND_BufferLength;
		posns[i].hEventNotify = hPosNotify[i];
	}

	hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, numdivisions, posns);
	if (hr != DS_OK) {
		free(posns);
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	free(posns);

	SetThreadPriority(isrthread, THREAD_PRIORITY_ABOVE_NORMAL);
	ResumeThread(isrthread);

	hr = IDirectSoundBuffer_Play(lpDSBSecondary, 0, 0, DSBPLAY_LOOPING);
	if (hr != DS_OK) {
		DSOUND_SetErrorCode(DSOUND_FailedPlaySecondary);
		return DSOUND_Error;
	}

	return DSOUND_Ok;
}
コード例 #9
0
ファイル: dsoundout.c プロジェクト: wosigh/duke3d
/*
 * DSOUND_Init
 * Initializes the DirectSound objects.
 */
int DSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize)
{
	HRESULT (WINAPI *aDirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
	HRESULT hr;
	DSBUFFERDESC dsbuf;
	WAVEFORMATEX wfex;
	DSBPOSITIONNOTIFY posn;
	
	if (DSOUND_Installed) {
		DSOUND_Shutdown();
	}

	printOSD("Initializing DirectSound...\n");
	
	if (!_DSOUND_CriticalSectionAlloced) {
		// initialize the critical section object we'll use to
		// simulate (dis|en)abling interrupts
		InitializeCriticalSection(&mutex);
		_DSOUND_CriticalSectionAlloced = TRUE;
	}

	printOSD("  - Loading DSOUND.DLL\n");
	hDSoundDLL = LoadLibrary("DSOUND.DLL");
	if (!hDSoundDLL) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_NoDLL);
		return DSOUND_Error;
	}

	aDirectSoundCreate = (void *)GetProcAddress(hDSoundDLL, "DirectSoundCreate");
	if (!aDirectSoundCreate) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_NoDirectSoundCreate);
		return DSOUND_Error;
	}

	printOSD("  - Creating DirectSound object\n");
	hr = aDirectSoundCreate(NULL, &lpDS, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedDSC);
		return DSOUND_Error;
	}

	hr = IDirectSound_SetCooperativeLevel(lpDS, (HWND)win_gethwnd(), DSSCL_EXCLUSIVE);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetCoopLevel);
		return DSOUND_Error;
	}

	printOSD("  - Creating primary buffer\n");
	ZeroMemory(&dsbuf, sizeof(dsbuf));
	dsbuf.dwSize = sizeof(DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
	hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBPrimary, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreatePrimary);
		return DSOUND_Error;
	}

	printOSD("  - Setting primary buffer format\n"
	         "      Channels:    %d\n"
		 "      Sample rate: %dHz\n"
		 "      Sample size: %d bits\n",
		 numchannels, mixrate, samplebits);
	ZeroMemory(&wfex, sizeof(wfex));
	wfex.wFormatTag      = WAVE_FORMAT_PCM;
	wfex.nChannels       = numchannels;
	wfex.nSamplesPerSec  = mixrate;
	wfex.wBitsPerSample  = samplebits;
	wfex.nBlockAlign     = (wfex.wBitsPerSample / 8) * wfex.nChannels;
	wfex.nAvgBytesPerSec = wfex.nBlockAlign * wfex.nSamplesPerSec;
	hr = IDirectSoundBuffer_SetFormat(lpDSBPrimary, &wfex);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetFormat);
		return DSOUND_Error;
	}

	printOSD("  - Creating secondary buffer\n");
	ZeroMemory(&dsbuf, sizeof(dsbuf));
	dsbuf.dwSize = sizeof(DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
	dsbuf.dwBufferBytes = buffersize;
	dsbuf.lpwfxFormat = &wfex;
	hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBSecondary, NULL);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreateSecondary);
		return DSOUND_Error;
	}

	hr = IDirectSoundBuffer_QueryInterface(lpDSBSecondary, &IID_IDirectSoundNotify, &lpDSNotify);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedQueryNotify);
		return DSOUND_Error;
	}

	hPosNotify = (HANDLE *)malloc(sizeof(HANDLE));
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}
	
	hPosNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (!hPosNotify) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedCreateNotifyEvent);
		return DSOUND_Error;
	}

	_DSOUND_BufferLength = 0;
	_DSOUND_NumBuffers   = 1;
	posn.dwOffset = 0;
	posn.hEventNotify = hPosNotify[0];

	hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, 1, &posn);
	if (hr != DS_OK) {
		DSOUND_Shutdown();
		DSOUND_SetErrorCode(DSOUND_FailedSetNotify);
		return DSOUND_Error;
	}

	DSOUND_Installed = TRUE;
	
	DSOUND_SetErrorCode(DSOUND_Ok);
	return DSOUND_Ok;
}
コード例 #10
0
ファイル: Audio.c プロジェクト: J301GH/emu-1964
void SetupDSoundBuffers(void) {
	LPDIRECTSOUNDBUFFER lpdsb;
    DSBUFFERDESC        dsPrimaryBuff, dsbdesc;
    WAVEFORMATEX        wfm;
    HRESULT             hr;
	int count;

    if (lpdsbuf) { CloseDLL(); InitiateAudio(AudioInfo);}

    if ( FAILED( hr = DirectSoundCreate( NULL, &lpds, NULL ) ) ) {
        return FALSE;
	}

    if ( FAILED( hr = IDirectSound8_SetCooperativeLevel(lpds, AudioInfo.hwnd, DSSCL_PRIORITY   ))) {
        return FALSE;
	}
    for ( count = 0; count < NUMCAPTUREEVENTS; count++ ) {
        rghEvent[count] = CreateEvent( NULL, FALSE, FALSE, NULL );
        if (rghEvent[count] == NULL ) { return FALSE; }
    }

	memset( &dsPrimaryBuff, 0, sizeof( DSBUFFERDESC ) ); 
    
	dsPrimaryBuff.dwSize        = sizeof( DSBUFFERDESC ); 
    dsPrimaryBuff.dwFlags       = DSBCAPS_PRIMARYBUFFER; 
    dsPrimaryBuff.dwBufferBytes = 0;  
    dsPrimaryBuff.lpwfxFormat   = NULL; 
    memset( &wfm, 0, sizeof( WAVEFORMATEX ) ); 

	wfm.wFormatTag = WAVE_FORMAT_PCM;
	wfm.nChannels = 2;
	wfm.nSamplesPerSec = 44100;
	wfm.wBitsPerSample = 16;
	wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels;
	wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;

	hr = IDirectSound8_CreateSoundBuffer(lpds,&dsPrimaryBuff, &lpdsb, NULL);
	
	if (SUCCEEDED ( hr ) ) {
		IDirectSoundBuffer8_SetFormat(lpdsb, &wfm );
	    IDirectSoundBuffer8_Play(lpdsb, 0, 0, DSBPLAY_LOOPING );
	}

	wfm.nSamplesPerSec = Frequency;
	wfm.wBitsPerSample = 16;
	wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels;
	wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;

    memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) ); 
    dsbdesc.dwSize = sizeof( DSBUFFERDESC ); 
    dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY;
    dsbdesc.dwBufferBytes = BufferSize * 3;  
    dsbdesc.lpwfxFormat = &wfm; 

	if ( FAILED( hr = IDirectSound8_CreateSoundBuffer(lpds, &dsbdesc, &lpdsbuf, NULL ) ) ) {
		DisplayError("Failed in creation of Play buffer 1");	
	}
	FillBufferWithSilence( lpdsbuf );

    rgdscbpn[0].dwOffset = ( BufferSize ) - 1;
    rgdscbpn[0].hEventNotify = rghEvent[0];
    rgdscbpn[1].dwOffset = ( BufferSize * 2) - 1;
    rgdscbpn[1].hEventNotify = rghEvent[1];
    rgdscbpn[2].dwOffset = ( BufferSize * 3) - 1;
    rgdscbpn[2].hEventNotify = rghEvent[2];
    rgdscbpn[3].dwOffset = DSBPN_OFFSETSTOP;
    rgdscbpn[3].hEventNotify = rghEvent[3];

    if ( FAILED( hr = IDirectSound8_QueryInterface(lpdsbuf, &IID_IDirectSoundNotify, ( VOID ** )&lpdsNotify ) ) ) {
		DisplayError("IDirectSound8_QueryInterface: Failed\n");
		return;
	}

    // Set capture buffer notifications.
    if ( FAILED( hr = IDirectSoundNotify_SetNotificationPositions(lpdsNotify, NUMCAPTUREEVENTS, rgdscbpn ) ) ) {
		DisplayError("IDirectSoundNotify_SetNotificationPositions: Failed");
		return;
    }

	//AddEffect();
}
コード例 #11
0
ファイル: dsound.c プロジェクト: deveck/Deveck.TAM
/*
 * Initialize DirectSound recorder device
 */
static pj_status_t init_capture_stream( struct dsound_stream *ds_strm,
				        int dev_id,
				        unsigned clock_rate,
				        unsigned channel_count,
				        unsigned samples_per_frame,
				        unsigned buffer_count)
{
    HRESULT hr;
    PCMWAVEFORMAT pcmwf; 
    DSCBUFFERDESC dscbdesc;
    DSBPOSITIONNOTIFY dsPosNotify[MAX_PACKET_BUFFER_COUNT];
    unsigned bytes_per_frame;
    unsigned i;


    PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL);


    /* Check device id */
    if (dev_id == -1)
	dev_id = 0;

    PJ_ASSERT_RETURN(dev_id>=0 && dev_id < (int)dev_count, PJ_EINVAL);

    /*
     * Creating recorder device.
     */
    hr = DirectSoundCaptureCreate(dev_info[dev_id].lpGuid, 
				  &ds_strm->ds.capture.lpDs, NULL);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);


    /* Init wave format to initialize buffer */
    init_waveformatex( &pcmwf, clock_rate, channel_count);
    bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE;

    /* 
     * Setup capture buffer using sound buffer structure that was passed
     * to play buffer creation earlier.
     */
    pj_bzero(&dscbdesc, sizeof(DSCBUFFERDESC));
    dscbdesc.dwSize = sizeof(DSCBUFFERDESC); 
    dscbdesc.dwFlags = DSCBCAPS_WAVEMAPPED ;
    dscbdesc.dwBufferBytes = buffer_count * bytes_per_frame; 
    dscbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; 

    hr = IDirectSoundCapture_CreateCaptureBuffer( ds_strm->ds.capture.lpDs,
						  &dscbdesc, 
						  &ds_strm->ds.capture.lpDsBuffer,
						  NULL);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    /*
     * Create event for play notification.
     */
    ds_strm->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
    if (ds_strm->hEvent == NULL)
	return pj_get_os_error();

    /*
     * Setup notifications for recording.
     */
    hr = IDirectSoundCaptureBuffer_QueryInterface( ds_strm->ds.capture.lpDsBuffer, 
						   &IID_IDirectSoundNotify, 
						   (LPVOID *)&ds_strm->lpDsNotify); 
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    
    for (i=0; i<buffer_count; ++i) {
	dsPosNotify[i].dwOffset = i * bytes_per_frame;
	dsPosNotify[i].hEventNotify = ds_strm->hEvent;
    }
    
    hr = IDirectSoundNotify_SetNotificationPositions( ds_strm->lpDsNotify, 
						      buffer_count, 
						      dsPosNotify);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    hr = IDirectSoundCaptureBuffer_GetCurrentPosition( ds_strm->ds.capture.lpDsBuffer, 
						       NULL, &ds_strm->dwBytePos );
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    ds_strm->timestamp.u64 = 0;
    ds_strm->dwDsBufferSize = buffer_count * bytes_per_frame;
    /*
     * Capture latency must always be on a frame boundry,
     * so compute it based off the calculated buffer_count.
     */
    ds_strm->latency = buffer_count * samples_per_frame * 1000 / clock_rate / 
		       channel_count;

    /* Done setting up recorder device. */
    PJ_LOG(5,(THIS_FILE, 
	      " DirectSound capture \"%s\" initialized (clock_rate=%d, "
	      "channel_count=%d, samples_per_frame=%d (%dms))",
	      dev_info[dev_id].info.name,
	      clock_rate, channel_count, samples_per_frame,
	      samples_per_frame * 1000 / clock_rate));

    return PJ_SUCCESS;
}
コード例 #12
0
ファイル: dsound.c プロジェクト: deveck/Deveck.TAM
/*
 * Initialize DirectSound player device.
 */
static pj_status_t init_player_stream( struct dsound_stream *ds_strm,
				       int dev_id,
				       unsigned clock_rate,
				       unsigned channel_count,
				       unsigned samples_per_frame,
				       unsigned buffer_count)
{
    HRESULT hr;
    HWND hwnd;
    PCMWAVEFORMAT pcmwf; 
    DSBUFFERDESC dsbdesc;
    DSBPOSITIONNOTIFY dsPosNotify[MAX_PACKET_BUFFER_COUNT];
    unsigned bytes_per_frame;
    unsigned max_latency;
    unsigned i;


    PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL);

    /* Check device ID */
    if (dev_id == -1)
	dev_id = 0;

    PJ_ASSERT_RETURN(dev_id>=0 && dev_id < (int)dev_count, PJ_EINVAL);

    /*
     * Create DirectSound device.
     */
    hr = DirectSoundCreate(dev_info[dev_id].lpGuid, &ds_strm->ds.play.lpDs, 
			   NULL);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    hwnd = GetForegroundWindow();
    if (hwnd == NULL) {
	hwnd = GetDesktopWindow();
    }    
    hr = IDirectSound_SetCooperativeLevel( ds_strm->ds.play.lpDs, hwnd, 
					   DSSCL_PRIORITY);
    if FAILED(hr)
	return PJ_RETURN_OS_ERROR(hr);
    
    /*
     * Set up wave format structure for initialize DirectSound play
     * buffer. 
     */
    init_waveformatex(&pcmwf, clock_rate, channel_count);
    bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE;

    /* Set up DSBUFFERDESC structure. */
    pj_bzero(&dsbdesc, sizeof(DSBUFFERDESC)); 
    dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
    dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY |
		      DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;

    dsbdesc.dwBufferBytes = buffer_count * bytes_per_frame;
    dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; 

    /*
     * Create DirectSound playback buffer. 
     */
    hr = IDirectSound_CreateSoundBuffer(ds_strm->ds.play.lpDs, &dsbdesc, 
					&ds_strm->ds.play.lpDsBuffer, NULL); 
    if (FAILED(hr) )
	return PJ_RETURN_OS_ERROR(hr);

    /*
     * Create event for play notification.
     */
    ds_strm->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
    if (ds_strm->hEvent == NULL)
	return pj_get_os_error();

    /*
     * Setup notification for play.
     */
    hr = IDirectSoundBuffer_QueryInterface( ds_strm->ds.play.lpDsBuffer, 
					    &IID_IDirectSoundNotify, 
					    (LPVOID *)&ds_strm->lpDsNotify); 
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);

    
    for (i=0; i<buffer_count; ++i) {
	dsPosNotify[i].dwOffset = i * bytes_per_frame;
	dsPosNotify[i].hEventNotify = ds_strm->hEvent;
    }
    
    hr = IDirectSoundNotify_SetNotificationPositions( ds_strm->lpDsNotify, 
						      buffer_count, 
						      dsPosNotify);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);


    hr = IDirectSoundBuffer_SetCurrentPosition(ds_strm->ds.play.lpDsBuffer, 0);
    if (FAILED(hr))
	return PJ_RETURN_OS_ERROR(hr);


    ds_strm->dwBytePos = 0;
    ds_strm->dwDsBufferSize = buffer_count * bytes_per_frame;
    ds_strm->timestamp.u64 = 0;
    /*
     * Play latency does not need to be on a frame boundry, it is just how far
     * ahead of the read pointer we set the write pointer.  So we should just
     * use the user configured latency.  However, if the latency measured in
     * bytes causes more buffers than we are allowed, we must cap the latency
     * at the time contained in 1-buffer_count.
     */
    max_latency = (1 - buffer_count) * samples_per_frame * 1000 / clock_rate /
        channel_count;
    ds_strm->latency = PJ_MIN(max_latency, snd_output_latency);

    /* Done setting up play device. */
    PJ_LOG(5,(THIS_FILE, 
	      " DirectSound player \"%s\" initialized (clock_rate=%d, "
	      "channel_count=%d, samples_per_frame=%d (%dms))",
	      dev_info[dev_id].info.name,
	      clock_rate, channel_count, samples_per_frame,
	      samples_per_frame * 1000 / clock_rate));

    return PJ_SUCCESS;
}