Example #1
0
/*
 * Check if there is space in playing buffer.
 */
static unsigned dsound_play_empty_size(struct dsound_stream *dsound_strm)
{
    HRESULT hr;
    long size_available;
    DWORD writePos, readPos;

    hr = IDirectSoundBuffer_GetCurrentPosition(dsound_strm->ds.play.lpDsBuffer, 
					       &readPos, &writePos);
    if FAILED(hr)
	return PJ_FALSE;

    if (readPos < dsound_strm->dwBytePos)
	size_available = readPos + dsound_strm->dwDsBufferSize - 
			 dsound_strm->dwBytePos;
    else
	size_available = readPos - dsound_strm->dwBytePos;

    return size_available;
}
Example #2
0
/*
	SNDDMA_GetDMAPos

	return the current sample position (in mono samples read)
	inside the recirculating dma buffer, so the mixing code will know
	how many sample are required to fill it up.
*/
int
SNDDMA_GetDMAPos (void)
{
	MMTIME      mmtime;
	int         s = 0;
	DWORD       dwWrite;

	if (dsound_init) {
		mmtime.wType = TIME_SAMPLES;
		IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmtime.u.sample, &dwWrite);
		s = mmtime.u.sample - mmstarttime.u.sample;
	} else if (wav_init) {
		s = snd_sent * WAV_BUFFER_SIZE;
	}


	s >>= sample16;

	s &= (shm->samples - 1);

	return s;
}
Example #3
0
/*
 * 再生位置通知のハンドラ
 */
static VOID OnNotifyPlayPos(int nBuffer)
{
	DWORD dwPlayPos;
	HRESULT hRet;

	// 再生終了領域を再生し終わった場合
	if(nPosCurArea[nBuffer] == nPosEndArea[nBuffer])
	{
		/* 再生を停止する */
		IDirectSoundBuffer_Stop(pDSBuffer[nBuffer]);
		IDirectSoundBuffer_SetCurrentPosition(pDSBuffer[nBuffer], 0);

		/* ストリームを停止状態にする */
		pStream[nBuffer] = NULL;
		return;	// 再生終了
	}

	// 再生位置を取得する
	hRet = IDirectSoundBuffer_GetCurrentPosition(pDSBuffer[nBuffer],
												 &dwPlayPos,
												 NULL);
	if(hRet != DS_OK)
		return;	// 再生位置の取得に失敗した

	/*
	 * 更新する領域上を再生中である場合
	 *  - 初回の通知のときに発生する
	 *  - または、遅延がバッファN周分のとき発生する
	 *  - バッファを更新しないで次の通知を待つ
	 *  - 遅延の場合は同じ音が繰り返し再生される(壊れたCDのように)
	 */
	if(dwPlayPos >= (DWORD)nPosCurArea[nBuffer] * AREA_BYTES &&
	   dwPlayPos < ((DWORD)nPosCurArea[nBuffer] + 1) * AREA_BYTES)
		return;	/* 更新しない */

	// バッファを更新する
	WriteNext(nBuffer);
}
Example #4
0
static int dx_bufferspace(void)
{
    DWORD play_cursor;
    int free_samples, buffer_samples;

    IDirectSoundBuffer_GetCurrentPosition(buffer, &play_cursor, NULL);
    /* We should properly distinguish between buffer empty and buffer fill
     * case. However, it's absolutely essential that the state where play and
     * write cursors overlap is read as buffer being filled with data. */
    if (play_cursor < buffer_offset) {
        free_samples = buffer_size - (buffer_offset - play_cursor);
    } else {
        free_samples = play_cursor - buffer_offset;
    }

    SDEBUG(("play=%d, ourwrite=%d, free=%d", play_cursor, buffer_offset, free_samples));

    free_samples /= (is16bit ? 2 : 1) * num_of_channels;

    /* test for underrun condition. It generally looks like we suddenly we have
     * a filled buffer instead of nearly empty one, because the play cursor
     * stepped over the write cursor. We generally have sound core calling
     * bufferspace() with every write, so we can rely on frequent calls here.
     */
    buffer_samples = buffer_size / (is16bit ? 2 : 1) / num_of_channels;
    if (free_samples < fragment_size
        && earlier_bufferspace > buffer_samples - fragment_size) {
        /* don't trigger again */
        earlier_bufferspace = 0;
        /* report underrun */
        return buffer_samples;
    }
    earlier_bufferspace = free_samples;

    return free_samples;
}
Example #5
0
float pest_get_pos(){
	unsigned __int64 time = 0;
	int play_pos;
	if(!playing) return 0;

	EnterCriticalSection(&critical);
	IDirectSoundBuffer_GetCurrentPosition( secondary, &play_pos, NULL );

	time += bytes_written;
	if( last_known <= play_pos ){
		time += play_pos - last_known;
	}else{
		time += (BUFFER_LEN*4)-(last_known-play_pos);
	}
	LeaveCriticalSection(&critical);
/*
	{
		char temp[256];
		sprintf( temp, "returning time: %f",  (float)((time/4)-(44100))*(1.f/44100.f)+pest_time_offset );
		OutputDebugString( temp );
	}
*/
	return (float)((time/4)-(44100))*(1.f/44100.f)+pest_time_offset;
}
Example #6
0
static void DSoundRender_UpdatePositions(DSoundRenderImpl *This, DWORD *seqwritepos, DWORD *minwritepos) {
    WAVEFORMATEX *wfx = (WAVEFORMATEX*)This->renderer.pInputPin->pin.mtCurrent.pbFormat;
    BYTE *buf1, *buf2;
    DWORD size1, size2, playpos, writepos, old_writepos, old_playpos, adv;
    BOOL writepos_set = This->writepos < This->buf_size;

    /* Update position and zero */
    old_writepos = This->writepos;
    old_playpos = This->last_playpos;
    if (old_writepos <= old_playpos)
        old_writepos += This->buf_size;

    IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, &playpos, &writepos);
    if (old_playpos > playpos) {
        adv = This->buf_size + playpos - old_playpos;
        This->play_time += time_from_pos(This, This->buf_size);
    } else
        adv = playpos - old_playpos;
    This->last_playpos = playpos;
    if (adv) {
        TRACE("Moving from %u to %u: clearing %u bytes\n", old_playpos, playpos, adv);
        IDirectSoundBuffer_Lock(This->dsbuffer, old_playpos, adv, (void**)&buf1, &size1, (void**)&buf2, &size2, 0);
        memset(buf1, wfx->wBitsPerSample == 8 ? 128  : 0, size1);
        memset(buf2, wfx->wBitsPerSample == 8 ? 128  : 0, size2);
        IDirectSoundBuffer_Unlock(This->dsbuffer, buf1, size1, buf2, size2);
    }
    *minwritepos = writepos;
    if (!writepos_set || old_writepos < writepos) {
        if (writepos_set) {
            This->writepos = This->buf_size;
            FIXME("Underrun of data occurred!\n");
        }
        *seqwritepos = writepos;
    } else
        *seqwritepos = This->writepos;
}
Example #7
0
static uint32_t RawCanWrite(void)
{
 DWORD CurWritePos,CurPlayPos=0;

 CheckDStatus();

 CurWritePos=0;

 if(IDirectSoundBuffer_GetCurrentPosition(ppbufw,&CurPlayPos,&CurWritePos)==DS_OK)
 {
//   FCEU_DispMessage("%8d",(CurWritePos-CurPlayPos));
 }
 CurWritePos=(CurPlayPos+BufHowMuch)%DSBufferSize;

 /*  If the current write pos is >= half the buffer size less than the to write pos,
     assume DirectSound has wrapped around.
 */

 if(((int32_t)ToWritePos-(int32_t)CurWritePos) >= (DSBufferSize/2))
 {
  CurWritePos+=DSBufferSize;
  //FCEU_printf("Fixit: %d,%d,%d\n",ToWritePos,CurWritePos,CurWritePos-DSBufferSize);
 }
 if(ToWritePos<CurWritePos)
 {
  int32_t howmuch=(int32_t)CurWritePos-(int32_t)ToWritePos;
  if(howmuch > BufHowMuch)      /* Oopsie.  Severe buffer overflow... */
  {
   //FCEU_printf("Ack");
   ToWritePos=CurWritePos%DSBufferSize;
  }
  return(CurWritePos-ToWritePos);
 }
 else
  return(0);
}
Example #8
0
static HRESULT TimeGet( aout_stream_sys_t *sys, vlc_tick_t *delay )
{
    DWORD read, status;
    HRESULT hr;
    ssize_t size;

    hr = IDirectSoundBuffer_GetStatus( sys->p_dsbuffer, &status );
    if( hr != DS_OK )
        return hr;
    if( !(status & DSBSTATUS_PLAYING) )
        return DSERR_INVALIDCALL ;

    hr = IDirectSoundBuffer_GetCurrentPosition( sys->p_dsbuffer, &read, NULL );
    if( hr != DS_OK )
        return hr;

    size = (ssize_t)read - sys->i_last_read;

    /* GetCurrentPosition cannot be trusted if the return doesn't change
     * Just return an error */
    if( size ==  0 )
        return DSERR_GENERIC ;
    else if( size < 0 )
      size += DS_BUF_SIZE;

    sys->i_data -= size;
    sys->i_last_read = read;

    if( sys->i_data < 0 )
        /* underrun */
        Flush(sys);

    *delay = vlc_tick_from_samples( sys->i_data / sys->i_bytes_per_sample, sys->i_rate );

    return DS_OK;
}
Example #9
0
HRESULT DSW_QueryOutputSpace( DSoundWrapper *dsw, long *bytesEmpty )
{
	HRESULT hr;
	DWORD   playCursor;
	DWORD   writeCursor;
	long    numBytesEmpty;
	long    playWriteGap;
// Query to see how much room is in buffer.
// Note: Even though writeCursor is not used, it must be passed to prevent DirectSound from dieing
// under WinNT. The Microsoft documentation says we can pass NULL but apparently not.
// Thanks to Max Rheiner for the fix.
	hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &writeCursor );
	if( hr != DS_OK )
	{
		return hr;
	}
	AddTraceMessage("playCursor", playCursor);
	AddTraceMessage("dsw_WriteOffset", dsw->dsw_WriteOffset);
// Determine size of gap between playIndex and WriteIndex that we cannot write into.
	playWriteGap = writeCursor - playCursor;
	if( playWriteGap < 0 ) playWriteGap += dsw->dsw_OutputSize; // unwrap
/* DirectSound doesn't have a large enough playCursor so we cannot detect wrap-around. */
/* Attempt to detect playCursor wrap-around and correct it. */
	if( dsw->dsw_OutputRunning && (dsw->dsw_CounterTicksPerBuffer.QuadPart != 0) )
	{
/* How much time has elapsed since last check. */
		LARGE_INTEGER   currentTime;
		LARGE_INTEGER   elapsedTime;
		long            bytesPlayed;
		long            bytesExpected;
		long            buffersWrapped;
		QueryPerformanceCounter( &currentTime );
		elapsedTime.QuadPart = currentTime.QuadPart - dsw->dsw_LastPlayTime.QuadPart;
		dsw->dsw_LastPlayTime = currentTime;
/* How many bytes does DirectSound say have been played. */
		bytesPlayed = playCursor - dsw->dsw_LastPlayCursor;
		if( bytesPlayed < 0 ) bytesPlayed += dsw->dsw_OutputSize; // unwrap
		dsw->dsw_LastPlayCursor = playCursor;
/* Calculate how many bytes we would have expected to been played by now. */
		bytesExpected = (long) ((elapsedTime.QuadPart * dsw->dsw_OutputSize) / dsw->dsw_CounterTicksPerBuffer.QuadPart);
		buffersWrapped = (bytesExpected - bytesPlayed) / dsw->dsw_OutputSize;
		if( buffersWrapped > 0 )
		{
			AddTraceMessage("playCursor wrapped! bytesPlayed", bytesPlayed );
			AddTraceMessage("playCursor wrapped! bytesExpected", bytesExpected );
			playCursor += (buffersWrapped * dsw->dsw_OutputSize);
			bytesPlayed += (buffersWrapped * dsw->dsw_OutputSize);
		}
	/* Maintain frame output cursor. */
		dsw->dsw_FramesPlayed += (bytesPlayed / dsw->dsw_BytesPerFrame);
	}
	numBytesEmpty = playCursor - dsw->dsw_WriteOffset;
	if( numBytesEmpty < 0 ) numBytesEmpty += dsw->dsw_OutputSize; // unwrap offset
/* Have we underflowed? */
	if( numBytesEmpty > (dsw->dsw_OutputSize - playWriteGap) )
	{
		if( dsw->dsw_OutputRunning )
		{
			dsw->dsw_OutputUnderflows += 1;
			AddTraceMessage("underflow detected! numBytesEmpty", numBytesEmpty );
		}
		dsw->dsw_WriteOffset = writeCursor;
		numBytesEmpty = dsw->dsw_OutputSize - playWriteGap;
	}
	*bytesEmpty = numBytesEmpty;
	return hr;
}
Example #10
0
static ALuint DSoundPlaybackProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData;
    DSBCAPS DSBCaps;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    BOOL Playing = FALSE;
    DWORD FrameSize;
    DWORD FragSize;
    DWORD avail;
    HRESULT err;

    SetRTPriority();

    memset(&DSBCaps, 0, sizeof(DSBCaps));
    DSBCaps.dwSize = sizeof(DSBCaps);
    err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps);
    if(FAILED(err))
    {
        ERR("Failed to get buffer caps: 0x%lx\n", err);
        ALCdevice_Lock(Device);
        aluHandleDisconnect(Device);
        ALCdevice_Unlock(Device);
        return 1;
    }

    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
    FragSize = Device->UpdateSize * FrameSize;

    IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL);
    while(!data->killNow)
    {
        // Get current play cursor
        IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;

        if(avail < FragSize)
        {
            if(!Playing)
            {
                err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING);
                if(FAILED(err))
                {
                    ERR("Failed to play buffer: 0x%lx\n", err);
                    ALCdevice_Lock(Device);
                    aluHandleDisconnect(Device);
                    ALCdevice_Unlock(Device);
                    return 1;
                }
                Playing = TRUE;
            }

            avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
            if(avail != WAIT_OBJECT_0)
                ERR("WaitForSingleObjectEx error: 0x%lx\n", avail);
            continue;
        }
        avail -= avail%FragSize;

        // Lock output buffer
        WriteCnt1 = 0;
        WriteCnt2 = 0;
        err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);

        // If the buffer is lost, restore it and lock
        if(err == DSERR_BUFFERLOST)
        {
            WARN("Buffer lost, restoring...\n");
            err = IDirectSoundBuffer_Restore(data->Buffer);
            if(SUCCEEDED(err))
            {
                Playing = FALSE;
                LastCursor = 0;
                err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
            }
        }

        // Successfully locked the output buffer
        if(SUCCEEDED(err))
        {
            // If we have an active context, mix data directly into output buffer otherwise fill with silence
            aluMixData(Device, WritePtr1, WriteCnt1/FrameSize);
            aluMixData(Device, WritePtr2, WriteCnt2/FrameSize);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
        {
            ERR("Buffer lock error: %#lx\n", err);
            ALCdevice_Lock(Device);
            aluHandleDisconnect(Device);
            ALCdevice_Unlock(Device);
            return 1;
        }

        // Update old write cursor location
        LastCursor += WriteCnt1+WriteCnt2;
        LastCursor %= DSBCaps.dwBufferBytes;
    }

    return 0;
}
Example #11
0
void m1sdr_TimeCheck(void)
{
	int nPlaySeg=0, nFollowingSeg=0;
	DWORD nPlay=0, nWrite=0;
	int nRet=0;

	if (!lpDS) return;

	// We should do nothing until nPlay has left nDSoundNextSeg
	IDirectSoundBuffer_GetCurrentPosition(lpSecB, &nPlay, &nWrite);

	nPlaySeg=nPlay/(nDSoundSegLen<<2);

	if (nPlaySeg>nDSoundSegCount-1) nPlaySeg=nDSoundSegCount-1;
	if (nPlaySeg<0) nPlaySeg=0; // important to ensure nPlaySeg clipped for below

	if (nDSoundNextSeg == nPlaySeg)
	{
		Sleep(200); // Don't need to do anything for a bit
		goto End;
	}

	// work out which seg we will fill next
	nFollowingSeg = nDSoundNextSeg; 
	WRAP_INC(nFollowingSeg)

	while (nDSoundNextSeg != nPlaySeg)
	{
		void *pData=NULL,*pData2=NULL; DWORD cbLen=0,cbLen2=0;

		// fill nNextSeg
		// Lock the relevant seg of the loop buffer
		nRet = IDirectSoundBuffer_Lock(lpSecB, nDSoundNextSeg*(nDSoundSegLen<<2), nDSoundSegLen<<2, &pData, &cbLen, &pData2, &cbLen2, 0);

		if (nRet>=0 && pData!=NULL)
		{
		  // Locked the seg okay - write the sound we calculated last time
			memcpy(pData, samples, nDSoundSegLen<<2);
		}
		// Unlock (2nd 0 is because we wrote nothing to second part)
		if (nRet>=0) IDirectSoundBuffer_Unlock(lpSecB, pData, cbLen, pData2, 0); 

		// generate more samples
		if ((m1sdr_Callback) && (!oss_pause))
		{
			//printf("callback: %ld samples\n", samples);
			m1sdr_Callback(nDSoundSegLen, samples);
		}
		else
		{
			memset(samples, 0, nDSoundSegLen*4);
		}

		waveLogFrame((unsigned char *)samples, nDSoundSegLen<<2);

		nDSoundNextSeg = nFollowingSeg;
		WRAP_INC(nFollowingSeg)
	}

End:
	return;
}
Example #12
0
static HRESULT WINAPI PrimaryBufferImpl_Lock(
	LPDIRECTSOUNDBUFFER iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
) {
	HRESULT hres;
        IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
        DirectSoundDevice *device = This->device;
	TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n",
		iface,
		writecursor,
		writebytes,
		lplpaudioptr1,
		audiobytes1,
		lplpaudioptr2,
		audiobytes2,
		flags,
		GetTickCount()
	);

        if (!audiobytes1)
            return DSERR_INVALIDPARAM;

	if (device->priolevel != DSSCL_WRITEPRIMARY) {
		WARN("failed priority check!\n");
		return DSERR_PRIOLEVELNEEDED;
	}

        /* when this flag is set, writecursor is meaningless and must be calculated */
	if (flags & DSBLOCK_FROMWRITECURSOR) {
		/* GetCurrentPosition does too much magic to duplicate here */
		hres = IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writecursor);
		if (hres != DS_OK) {
			WARN("IDirectSoundBuffer_GetCurrentPosition failed\n");
			return hres;
		}
	}

        /* when this flag is set, writebytes is meaningless and must be set */
	if (flags & DSBLOCK_ENTIREBUFFER)
		writebytes = device->buflen;

        if (writecursor >= device->buflen) {
                WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
		     writecursor, device->buflen);
                return DSERR_INVALIDPARAM;
        }

        if (writebytes > device->buflen) {
                WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
		     writebytes, device->buflen);
                return DSERR_INVALIDPARAM;
        }

	if (writecursor+writebytes <= device->buflen) {
		*(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
		*audiobytes1 = writebytes;
		if (lplpaudioptr2)
			*(LPBYTE*)lplpaudioptr2 = NULL;
		if (audiobytes2)
			*audiobytes2 = 0;
		TRACE("->%d.0\n",writebytes);
	} else {
		*(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
		*audiobytes1 = device->buflen-writecursor;
		if (lplpaudioptr2)
			*(LPBYTE*)lplpaudioptr2 = device->buffer;
		if (audiobytes2)
			*audiobytes2 = writebytes-(device->buflen-writecursor);
		TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
	}
	return DS_OK;
}
Example #13
0
static INLINE void get_positions(dsound_t *ds, DWORD *read_ptr, DWORD *write_ptr)
{
   IDirectSoundBuffer_GetCurrentPosition(ds->dsb, read_ptr, write_ptr);
}
Example #14
0
static int dsound_run_out (HWVoiceOut *hw, int live)
{
    int err;
    HRESULT hr;
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
    LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
    int len, hwshift;
    DWORD blen1, blen2;
    DWORD len1, len2;
    DWORD decr;
    DWORD wpos, ppos, old_pos;
    LPVOID p1, p2;
    int bufsize;
    dsound *s = ds->s;
    DSoundConf *conf = &s->conf;

    if (!dsb) {
        dolog ("Attempt to run empty with playback buffer\n");
        return 0;
    }

    hwshift = hw->info.shift;
    bufsize = hw->samples << hwshift;

    hr = IDirectSoundBuffer_GetCurrentPosition (
        dsb,
        &ppos,
        ds->first_time ? &wpos : NULL
        );
    if (FAILED (hr)) {
        dsound_logerr (hr, "Could not get playback buffer position\n");
        return 0;
    }

    len = live << hwshift;

    if (ds->first_time) {
        if (conf->latency_millis) {
            DWORD cur_blat;

            cur_blat = audio_ring_dist (wpos, ppos, bufsize);
            ds->first_time = 0;
            old_pos = wpos;
            old_pos +=
                millis_to_bytes (&hw->info, conf->latency_millis) - cur_blat;
            old_pos %= bufsize;
            old_pos &= ~hw->info.align;
        }
        else {
            old_pos = wpos;
        }
#ifdef DEBUG_DSOUND
        ds->played = 0;
        ds->mixed = 0;
#endif
    }
    else {
        if (ds->old_pos == ppos) {
#ifdef DEBUG_DSOUND
            dolog ("old_pos == ppos\n");
#endif
            return 0;
        }

#ifdef DEBUG_DSOUND
        ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize);
#endif
        old_pos = ds->old_pos;
    }

    if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
        len = ppos - old_pos;
    }
    else {
        if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) {
            len = bufsize - old_pos + ppos;
        }
    }

    if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) {
        dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
               len, bufsize, old_pos, ppos);
        return 0;
    }

    len &= ~hw->info.align;
    if (!len) {
        return 0;
    }

#ifdef DEBUG_DSOUND
    ds->old_ppos = ppos;
#endif
    err = dsound_lock_out (
        dsb,
        &hw->info,
        old_pos,
        len,
        &p1, &p2,
        &blen1, &blen2,
        0,
        s
        );
    if (err) {
        return 0;
    }

    len1 = blen1 >> hwshift;
    len2 = blen2 >> hwshift;
    decr = len1 + len2;

    if (p1 && len1) {
        dsound_write_sample (hw, p1, len1);
    }

    if (p2 && len2) {
        dsound_write_sample (hw, p2, len2);
    }

    dsound_unlock_out (dsb, p1, p2, blen1, blen2);
    ds->old_pos = (old_pos + (decr << hwshift)) % bufsize;

#ifdef DEBUG_DSOUND
    ds->mixed += decr << hwshift;

    dolog ("played %lu mixed %lu diff %ld sec %f\n",
           ds->played,
           ds->mixed,
           ds->mixed - ds->played,
           abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);
#endif
    return decr;
}
Example #15
0
DWORD WINAPI fluid_dsound_audio_run(LPVOID lpParameter)
{
  fluid_dsound_audio_driver_t* dev = (fluid_dsound_audio_driver_t*) lpParameter;
  short *buf1, *buf2;
  DWORD bytes1, bytes2;
  DWORD cur_position, frames, play_position, write_position, bytes;
  HRESULT res;

  cur_position = 0;

  /* boost the priority of the audio thread */
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

  IDirectSoundBuffer_Play(dev->sec_buffer, 0, 0, DSBPLAY_LOOPING);

  while (dev->cont) {

    IDirectSoundBuffer_GetCurrentPosition(dev->sec_buffer, &play_position, &write_position);

    if (cur_position <= play_position) {
      bytes = play_position - cur_position;
    } else if ((play_position < cur_position) && (write_position <= cur_position)) {
      bytes = dev->queue_byte_size + play_position - cur_position;
    } else {
      bytes = 0;
    }

    if (bytes >= dev->buffer_byte_size) {

      /* Lock */
      res = IDirectSoundBuffer_Lock(dev->sec_buffer, cur_position, bytes, (void*) &buf1, &bytes1, (void*) &buf2, &bytes2, 0);

      if ((res != DS_OK) || (buf1 == NULL)) {
	FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. System lockup might follow. Exiting.");
	ExitProcess(0);
      }

      /* fill the first part of the buffer */
      if (bytes1 > 0) {
	frames = bytes1 / dev->frame_size;
	dev->write(dev->synth, frames, buf1, 0, 2, buf1, 1, 2);
	cur_position += frames * dev->frame_size;
      }

      /* fill the second part of the buffer */
      if ((buf2 != NULL) && (bytes2 > 0)) {
	frames = bytes2 / dev->frame_size;
	dev->write(dev->synth, frames, buf2, 0, 2, buf2, 1, 2);
	cur_position += frames * dev->frame_size;
      }

      /* Unlock */
      IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, buf2, bytes2);

      if (cur_position >= dev->queue_byte_size) {
	cur_position -= dev->queue_byte_size;
      }

    } else {
      Sleep(1);
    }
  }

  ExitThread(0);
  return 0; /* never reached */
}
Example #16
0
static HRESULT test_block_align(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND dso=NULL;
    LPDIRECTSOUNDBUFFER secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSBCAPS dsbcaps;
    WAVEFORMATEX wfx;
    DWORD pos, pos2;
    int ref;

    /* Create the DirectSound object */
    rc=pDirectSoundCreate(lpGuid,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
       "DirectSoundCreate() failed: %08x\n",rc);
    if (rc!=DS_OK)
        return rc;

    init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
    bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
    bufdesc.lpwfxFormat=&wfx;
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
    ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
       "should have returned DS_OK, returned: %08x\n", rc);

    if (rc==DS_OK && secondary!=NULL) {
        ZeroMemory(&dsbcaps, sizeof(dsbcaps));
        dsbcaps.dwSize = sizeof(dsbcaps);
        rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
        ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
           "returned: %08x\n", rc);
        if (rc==DS_OK && wfx.nBlockAlign > 1)
        {
            ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
               "Buffer size not a multiple of nBlockAlign: requested %d, "
               "got %d, should be %d\n", bufdesc.dwBufferBytes,
               dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);

            rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
            ok(rc == DS_OK, "Could not set position to 0: %08x\n", rc);
            rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL);
            ok(rc == DS_OK, "Could not get position: %08x\n", rc);
            rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1);
            ok(rc == DS_OK, "Could not set position to 1: %08x\n", rc);
            rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL);
            ok(rc == DS_OK, "Could not get new position: %08x\n", rc);
            ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2);
        }
        ref=IDirectSoundBuffer_Release(secondary);
        ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
           "should have 0\n",ref);
    }

    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}
static guint
gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length)
{
  GstDirectSoundSink *dsoundsink;
  DWORD dwStatus;
  HRESULT hRes;
  LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL;
  DWORD dwSizeBuffer1, dwSizeBuffer2;
  DWORD dwCurrentPlayCursor;

  dsoundsink = GST_DIRECTSOUND_SINK (asink);

  /* Fix endianness */
  if (dsoundsink->buffer_format == GST_IEC958)
    _swab (data, data, length);

  GST_DSOUND_LOCK (dsoundsink);

  /* get current buffer status */
  hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);

  /* get current play cursor position */
  hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
      &dwCurrentPlayCursor, NULL);

  if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) {
    DWORD dwFreeBufferSize;

  calculate_freesize:
    /* calculate the free size of the circular buffer */
    if (dwCurrentPlayCursor < dsoundsink->current_circular_offset)
      dwFreeBufferSize =
          dsoundsink->buffer_size - (dsoundsink->current_circular_offset -
          dwCurrentPlayCursor);
    else
      dwFreeBufferSize =
          dwCurrentPlayCursor - dsoundsink->current_circular_offset;

    if (length >= dwFreeBufferSize) {
      Sleep (100);
      hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
          &dwCurrentPlayCursor, NULL);

      hRes =
          IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);
      if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING))
        goto calculate_freesize;
      else {
        dsoundsink->first_buffer_after_reset = FALSE;
        GST_DSOUND_UNLOCK (dsoundsink);
        return 0;
      }
    }
  }

  if (dwStatus & DSBSTATUS_BUFFERLOST) {
    hRes = IDirectSoundBuffer_Restore (dsoundsink->pDSBSecondary);      /*need a loop waiting the buffer is restored?? */

    dsoundsink->current_circular_offset = 0;
  }

  hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary,
      dsoundsink->current_circular_offset, length, &pLockedBuffer1,
      &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L);

  if (SUCCEEDED (hRes)) {
    // Write to pointers without reordering.
    memcpy (pLockedBuffer1, data, dwSizeBuffer1);
    if (pLockedBuffer2 != NULL)
      memcpy (pLockedBuffer2, (LPBYTE) data + dwSizeBuffer1, dwSizeBuffer2);

    // Update where the buffer will lock (for next time)
    dsoundsink->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2;
    dsoundsink->current_circular_offset %= dsoundsink->buffer_size;     /* Circular buffer */

    hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer1,
        dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2);
  }

  /* if the buffer was not in playing state yet, call play on the buffer 
     except if this buffer is the fist after a reset (base class call reset and write a buffer when setting the sink to pause) */
  if (!(dwStatus & DSBSTATUS_PLAYING) &&
      dsoundsink->first_buffer_after_reset == FALSE) {
    hRes = IDirectSoundBuffer_Play (dsoundsink->pDSBSecondary, 0, 0,
        DSBPLAY_LOOPING);
  }

  dsoundsink->first_buffer_after_reset = FALSE;

  GST_DSOUND_UNLOCK (dsoundsink);

  return length;
}
Example #18
0
DWORD WINAPI pest_thread_proc( LPVOID jalla ){
	short *buffer1;
	short *buffer2;
	int play_pos;
	DWORD len1;
	DWORD len2;

	ready_to_quit = FALSE;

	if(done) return 0;
	done = FALSE;

	SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

	IDirectSoundBuffer_Lock( secondary, 0, BUFFER_LEN*4, (void**)&buffer1, &len1, (void**)&buffer2, &len2, DSBLOCK_ENTIREBUFFER);
	bytes_written = fill_buffer( buffer1, len1 );
	if(buffer2) bytes_written+= fill_buffer( buffer2, len2 );

	EnterCriticalSection(&critical);
	last_known = (int)(bytes_written%(BUFFER_LEN*4));
	LeaveCriticalSection(&critical);

	IDirectSoundBuffer_Unlock(secondary,(void*)buffer1,len1,(void*)buffer2,len2);
	IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
	IDirectSoundBuffer_Play(secondary, 0, 0, DSBPLAY_LOOPING);

	playing = TRUE;
	Sleep(100);

	while( !done )
	{
		short buffer[BUFFER_LEN*2];
		int to_write;
		DWORD written;

		IDirectSoundBuffer_GetCurrentPosition( secondary, &play_pos, NULL );

		if( last_known < play_pos ){
			to_write = play_pos - last_known;
			OutputDebugString( "Last known smaller than play pos" );
		}else{
			to_write = (BUFFER_LEN*4)-(last_known-play_pos);
		}

		while( IDirectSoundBuffer_Lock( secondary, last_known, to_write, (void**)&buffer1, &len1, (void**)&buffer2, &len2, 0)!=DS_OK){
			OutputDebugString("Trying to restore");
			IDirectSoundBuffer_Restore( secondary );
			IDirectSoundBuffer_Play( secondary, 0, 0, DSBPLAY_LOOPING);
		}

		written = fill_buffer( (short*)buffer, len1+len2 );
		memcpy(buffer1,buffer,len1);

		if(written>len1) memcpy(buffer2,(char*)buffer+len1,written-len1);

		IDirectSoundBuffer_Unlock( secondary, (void*)buffer1, len1, (void*)buffer2, len2 );

		EnterCriticalSection(&critical);
		bytes_written += written;
		last_known = (int)(bytes_written%(BUFFER_LEN*4));
		LeaveCriticalSection(&critical);
		Sleep(100);
	}

	playing=FALSE;
	ready_to_quit=TRUE;

	DeleteCriticalSection(&critical);

	return 0;
}
Example #19
0
static int ds_rsd_open(void* data, wav_header_t *w)
{
    ds_t* ds = data;

    if (DirectSoundCreate(NULL, &ds->ds, NULL) != DS_OK)
        return -1;

    if (IDirectSound_SetCooperativeLevel(ds->ds, GetDesktopWindow(), DSSCL_NORMAL) != DS_OK)
        return -1;

    int bits = 16;
    ds->fmt = w->rsd_format;
    ds->conv = converter_fmt_to_s16ne(w->rsd_format);

    ds->rings = 16;
    ds->latency = DEFAULT_CHUNK_SIZE * 2;

    WAVEFORMATEX wfx = {
        .wFormatTag = WAVE_FORMAT_PCM,
        .nChannels = w->numChannels,
        .nSamplesPerSec = w->sampleRate,
        .wBitsPerSample = bits,
        .nBlockAlign = w->numChannels * bits / 8,
        .nAvgBytesPerSec = w->sampleRate * w->numChannels * bits / 8,
    };

    DSBUFFERDESC bufdesc = {
        .dwSize = sizeof(DSBUFFERDESC),
        .dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS,
        .dwBufferBytes = ds->rings * ds->latency,
        .lpwfxFormat = &wfx,
    };

    if (IDirectSound_CreateSoundBuffer(ds->ds, &bufdesc, &ds->dsb, 0) != DS_OK)
        return -1;

    IDirectSoundBuffer_SetCurrentPosition(ds->dsb, 0);
    clear_buffers(ds);
    IDirectSoundBuffer_Play(ds->dsb, 0, 0, DSBPLAY_LOOPING);

    return 0;
}

static size_t ds_rsd_write(void *data, const void* inbuf, size_t size)
{
    ds_t *ds = data;

    size_t osize = size;

    uint8_t convbuf[2 * size];
    const uint8_t *buffer_ptr = inbuf;

    if (ds->conv != RSD_NULL)
    {
        if (rsnd_format_to_bytes(ds->fmt) == 1)
            osize = 2 * size;
        else if (rsnd_format_to_bytes(ds->fmt) == 4)
            osize = size / 2;

        memcpy(convbuf, inbuf, size);

        audio_converter(convbuf, ds->fmt, ds->conv, size);
        buffer_ptr = convbuf;
    }

    // With this approach we are prone to underruns which would "ring",
    // but the RSound API does not really encourage letting stuff underrun anyways.
    ds->writering = (ds->writering + 1) % ds->rings;
    for (;;)
    {
        DWORD pos;
        IDirectSoundBuffer_GetCurrentPosition(ds->dsb, &pos, 0);
        unsigned activering = pos / ds->latency;
        if (activering != ds->writering)
            break;

        Sleep(1);
    }

    void *output1, *output2;
    DWORD size1, size2;

    HRESULT res;
    if ((res = IDirectSoundBuffer_Lock(ds->dsb, ds->writering * ds->latency, osize,
                                       &output1, &size1, &output2, &size2, 0)) != DS_OK)
    {
        if (res != DSERR_BUFFERLOST)
            return 0;

        if (IDirectSoundBuffer_Restore(ds->dsb) != DS_OK)
            return 0;

        if (IDirectSoundBuffer_Lock(ds->dsb, ds->writering * ds->latency, osize,
                                    &output1, &size1, &output2, &size2, 0) != DS_OK)
            return 0;
    }

    memcpy(output1, buffer_ptr, size1);
    memcpy(output2, buffer_ptr + size1, size2);

    IDirectSoundBuffer_Unlock(ds->dsb, output1, size1, output2, size2);

    return size;
}

static int ds_rsd_latency(void* data)
{
    ds_t *ds = data;

    DWORD pos;
    IDirectSoundBuffer_GetCurrentPosition(ds->dsb, &pos, 0);
    DWORD next_writepos = ((ds->writering + 1) % ds->rings) * ds->latency;
    if (next_writepos <= pos)
        next_writepos += ds->rings * ds->latency;

    int delta = next_writepos - pos;

    if (rsnd_format_to_bytes(ds->fmt) == 1)
        delta /= 2;
    else if (rsnd_format_to_bytes(ds->fmt) == 4)
        delta *= 2;

    return delta;
}
Example #20
0
soundplay_t *SND_InitPlayback(int speed, int bits)
{
	int ret;
	DSBCAPS caps;
	DSBUFFERDESC bufdesc;
	LPDIRECTSOUND ds;
	dsplay_t *hnd;
	WAVEFORMATEX	format; 

	if (!hInstDS)
	{
		hInstDS = LoadLibrary("dsound.dll");
		
		if (hInstDS == NULL)
		{
			printf ("Couldn't load dsound.dll\n");
			return NULL;
		}

		pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");

		if (!pDirectSoundCreate)
		{
			printf ("Couldn't get DS proc addr\n");
			return NULL;
		}
				
//		pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA");
	}

	ds = NULL;
	pDirectSoundCreate(NULL, &ds, NULL);

	if (!ds)
		return NULL;
	hnd = malloc(sizeof(*hnd));
	memset(hnd, 0, sizeof(*hnd));

	hnd->funcs.update = DSOUND_UpdatePlayback;
	hnd->funcs.close = DSOUND_Shutdown;

	hnd->ds = ds;
	hnd->sampbytes = bits/8;

	if (FAILED(IDirectSound_SetCooperativeLevel (hnd->ds, GetDesktopWindow(), DSSCL_EXCLUSIVE)))
		printf("SetCooperativeLevel failed\n");

	memset(&bufdesc, 0, sizeof(bufdesc));
	bufdesc.dwSize = sizeof(bufdesc);
//	bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS;	//so we hear it if quake is loaded
	bufdesc.dwFlags |= DSBCAPS_PRIMARYBUFFER; //so we can set speed
	bufdesc.dwFlags |= DSBCAPS_CTRLVOLUME;
	bufdesc.lpwfxFormat = NULL;
	bufdesc.dwBufferBytes = 0;

	format.wFormatTag = WAVE_FORMAT_PCM;
	format.cbSize = 0;

	format.nChannels = 1;
    format.wBitsPerSample = bits;
    format.nSamplesPerSec = speed;
    format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
    format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;

	ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);

	if (!hnd->dsbuf)
	{
		printf("Couldn't create primary buffer\n");
		DSOUND_Shutdown(&hnd->funcs);
		return NULL;
	}

	if (FAILED(IDirectSoundBuffer_SetFormat(hnd->dsbuf, &format)))
		printf("SetFormat failed\n");

	//and now make a secondary buffer
	bufdesc.dwFlags = 0;
	bufdesc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
	bufdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
	bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS;
	bufdesc.dwBufferBytes = speed * format.nChannels * hnd->sampbytes;
	bufdesc.lpwfxFormat = &format;

	ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);
	if (!hnd->dsbuf)
	{
		printf("Couldn't create secondary buffer\n");
		DSOUND_Shutdown(&hnd->funcs);
		return NULL;
	}








	memset(&caps, 0, sizeof(caps));
	caps.dwSize = sizeof(caps);
	IDirectSoundBuffer_GetCaps(hnd->dsbuf, &caps);
	hnd->buffersize = caps.dwBufferBytes / hnd->sampbytes;

	//clear out the buffer
	{
		char *buffer;
		int buffersize=0;
		IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
		ret = IDirectSoundBuffer_Lock(hnd->dsbuf, 0, hnd->buffersize*hnd->sampbytes, (void**)&buffer, &buffersize, NULL, NULL, 0);
		memset(buffer, 0, buffersize);
		IDirectSoundBuffer_Unlock(hnd->dsbuf, buffer, buffersize, NULL, 0);
		IDirectSoundBuffer_Stop(hnd->dsbuf);
	}
//DSERR_INVALIDPARAM
	IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
	

	IDirectSoundBuffer_GetCurrentPosition(hnd->dsbuf, &hnd->readpos, &hnd->writepos);

	hnd->writepos = hnd->readpos + speed / 2;	//position our write position a quater of a second infront of the read position

	printf("%i %i\n", 100*hnd->readpos / hnd->buffersize, 100*hnd->writepos / hnd->buffersize);

	return &hnd->funcs;
}
Example #21
0
static ALuint DSoundProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    DSoundData *pData = (DSoundData*)pDevice->ExtraData;
    DSBCAPS DSBCaps;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    DWORD FrameSize;
    DWORD FragSize;
    DWORD avail;
    HRESULT err;

    SetRTPriority();

    memset(&DSBCaps, 0, sizeof(DSBCaps));
    DSBCaps.dwSize = sizeof(DSBCaps);
    err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
    if(FAILED(err))
    {
        AL_PRINT("Failed to get buffer caps: 0x%lx\n", err);
        aluHandleDisconnect(pDevice);
        return 1;
    }

    FrameSize = aluFrameSizeFromFormat(pDevice->Format);
    FragSize = pDevice->UpdateSize * FrameSize;

    IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
    while(!pData->killNow)
    {
        // Get current play and write cursors
        IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;

        if(avail < FragSize)
        {
            Sleep(1);
            continue;
        }
        avail -= avail%FragSize;

        // Lock output buffer
        WriteCnt1 = 0;
        WriteCnt2 = 0;
        err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);

        // If the buffer is lost, restore it, play and lock
        if(err == DSERR_BUFFERLOST)
        {
            err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
        }

        // Successfully locked the output buffer
        if(SUCCEEDED(err))
        {
            // If we have an active context, mix data directly into output buffer otherwise fill with silence
            aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize);
            aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
            AL_PRINT("Buffer lock error: %#lx\n", err);

        // Update old write cursor location
        LastCursor += WriteCnt1+WriteCnt2;
        LastCursor %= DSBCaps.dwBufferBytes;
    }

    return 0;
}
Example #22
0
HRESULT DSW_InitOutputBuffer( DSoundWrapper *dsw, unsigned long nFrameRate, int nChannels, int bytesPerBuffer )
{
	DWORD          dwDataLen;
	DWORD          playCursor;
	HRESULT        result;
	LPDIRECTSOUNDBUFFER pPrimaryBuffer;
	HWND           hWnd;
	HRESULT        hr;
	WAVEFORMATEX   wfFormat;
	DSBUFFERDESC   primaryDesc;
	DSBUFFERDESC   secondaryDesc;
	unsigned char* pDSBuffData;
	LARGE_INTEGER  counterFrequency;
	dsw->dsw_OutputSize = bytesPerBuffer;
	dsw->dsw_OutputRunning = FALSE;
	dsw->dsw_OutputUnderflows = 0;
	dsw->dsw_FramesWritten = 0;
	dsw->dsw_BytesPerFrame = nChannels * sizeof(short);
// We were using getForegroundWindow() but sometimes the ForegroundWindow may not be the
// applications's window. Also if that window is closed before the Buffer is closed
// then DirectSound can crash. (Thanks for Scott Patterson for reporting this.)
// So we will use GetDesktopWindow() which was suggested by Miller Puckette.
//	hWnd = GetForegroundWindow();
	hWnd = GetDesktopWindow();
// Set cooperative level to DSSCL_EXCLUSIVE so that we can get 16 bit output, 44.1 KHz.
// Exclusize also prevents unexpected sounds from other apps during a performance.
	if ((hr = IDirectSound_SetCooperativeLevel( dsw->dsw_pDirectSound,
			hWnd, DSSCL_EXCLUSIVE)) != DS_OK)
	{
		return hr;
	}
// -----------------------------------------------------------------------
// Create primary buffer and set format just so we can specify our custom format.
// Otherwise we would be stuck with the default which might be 8 bit or 22050 Hz.
// Setup the primary buffer description
	ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC));
	primaryDesc.dwSize        = sizeof(DSBUFFERDESC);
	primaryDesc.dwFlags       = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth
	primaryDesc.dwBufferBytes = 0;
	primaryDesc.lpwfxFormat   = NULL;
// Create the buffer
	if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,
			&primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) return result;
// Define the buffer format
	wfFormat.wFormatTag = WAVE_FORMAT_PCM;
	wfFormat.nChannels = nChannels;
	wfFormat.nSamplesPerSec = nFrameRate;
	wfFormat.wBitsPerSample = 8 * sizeof(short);
	wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8;
	wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign;
	wfFormat.cbSize = 0;  /* No extended format info. */
// Set the primary buffer's format
	if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &wfFormat)) != DS_OK) return result;
// ----------------------------------------------------------------------
// Setup the secondary buffer description
	ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC));
	secondaryDesc.dwSize = sizeof(DSBUFFERDESC);
	secondaryDesc.dwFlags =  DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
	secondaryDesc.dwBufferBytes = bytesPerBuffer;
	secondaryDesc.lpwfxFormat = &wfFormat;
// Create the secondary buffer
	if ((result = IDirectSound_CreateSoundBuffer( dsw->dsw_pDirectSound,
			&secondaryDesc, &dsw->dsw_OutputBuffer, NULL)) != DS_OK) return result;
// Lock the DS buffer
	if ((result = IDirectSoundBuffer_Lock( dsw->dsw_OutputBuffer, 0, dsw->dsw_OutputSize, (LPVOID*)&pDSBuffData,
	  &dwDataLen, NULL, 0, 0)) != DS_OK) return result;
// Zero the DS buffer
	ZeroMemory(pDSBuffData, dwDataLen);
// Unlock the DS buffer
	if ((result = IDirectSoundBuffer_Unlock( dsw->dsw_OutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) return result;
	if( QueryPerformanceFrequency( &counterFrequency ) )
	{
		int framesInBuffer = bytesPerBuffer / (nChannels * sizeof(short));
		dsw->dsw_CounterTicksPerBuffer.QuadPart = (counterFrequency.QuadPart * framesInBuffer) / nFrameRate;
		AddTraceMessage("dsw_CounterTicksPerBuffer = %d\n", dsw->dsw_CounterTicksPerBuffer.LowPart );
	}
	else
	{
		dsw->dsw_CounterTicksPerBuffer.QuadPart = 0;
	}
// Let DSound set the starting write position because if we set it to zero, it looks like the
// buffer is full to begin with. This causes a long pause before sound starts when using large buffers.
	hr = IDirectSoundBuffer_GetCurrentPosition( dsw->dsw_OutputBuffer, &playCursor, &dsw->dsw_WriteOffset );
	if( hr != DS_OK )
	{
		return hr;
	}
	dsw->dsw_FramesWritten = dsw->dsw_WriteOffset / dsw->dsw_BytesPerFrame;
	/* printf("DSW_InitOutputBuffer: playCursor = %d, writeCursor = %d\n", playCursor, dsw->dsw_WriteOffset ); */
	return DS_OK;
}
Example #23
0
static DWORD CALLBACK MCICDA_playLoop(void *ptr)
{
    WINE_MCICDAUDIO *wmcda = (WINE_MCICDAUDIO*)ptr;
    DWORD lastPos, curPos, endPos, br;
    void *cdData;
    DWORD lockLen, fragLen;
    DSBCAPS caps;
    RAW_READ_INFO rdInfo;
    HRESULT hr = DS_OK;

    memset(&caps, 0, sizeof(caps));
    caps.dwSize = sizeof(caps);
    hr = IDirectSoundBuffer_GetCaps(wmcda->dsBuf, &caps);

    fragLen = caps.dwBufferBytes/CDDA_FRAG_COUNT;
    curPos = lastPos = 0;
    endPos = ~0u;
    while (SUCCEEDED(hr) && endPos != lastPos &&
           WaitForSingleObject(wmcda->stopEvent, 0) != WAIT_OBJECT_0) {
        hr = IDirectSoundBuffer_GetCurrentPosition(wmcda->dsBuf, &curPos, NULL);
        if ((curPos-lastPos+caps.dwBufferBytes)%caps.dwBufferBytes < fragLen) {
            Sleep(1);
            continue;
        }

        EnterCriticalSection(&wmcda->cs);
        rdInfo.DiskOffset.QuadPart = wmcda->start<<11;
        rdInfo.SectorCount = min(fragLen/RAW_SECTOR_SIZE, wmcda->end-wmcda->start);
        rdInfo.TrackMode = CDDA;

        hr = IDirectSoundBuffer_Lock(wmcda->dsBuf, lastPos, fragLen, &cdData, &lockLen, NULL, NULL, 0);
        if (hr == DSERR_BUFFERLOST) {
            if(FAILED(IDirectSoundBuffer_Restore(wmcda->dsBuf)) ||
               FAILED(IDirectSoundBuffer_Play(wmcda->dsBuf, 0, 0, DSBPLAY_LOOPING))) {
                LeaveCriticalSection(&wmcda->cs);
                break;
            }
            hr = IDirectSoundBuffer_Lock(wmcda->dsBuf, lastPos, fragLen, &cdData, &lockLen, NULL, NULL, 0);
        }

        if (SUCCEEDED(hr)) {
            if (rdInfo.SectorCount > 0) {
                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_RAW_READ, &rdInfo, sizeof(rdInfo), cdData, lockLen, &br, NULL))
                    WARN("CD read failed at sector %d: 0x%x\n", wmcda->start, GetLastError());
            }
            if (rdInfo.SectorCount*RAW_SECTOR_SIZE < lockLen) {
                if(endPos == ~0u) endPos = lastPos;
                memset((BYTE*)cdData + rdInfo.SectorCount*RAW_SECTOR_SIZE, 0,
                       lockLen - rdInfo.SectorCount*RAW_SECTOR_SIZE);
            }
            hr = IDirectSoundBuffer_Unlock(wmcda->dsBuf, cdData, lockLen, NULL, 0);
        }

        lastPos += fragLen;
        lastPos %= caps.dwBufferBytes;
        wmcda->start += rdInfo.SectorCount;

        LeaveCriticalSection(&wmcda->cs);
    }
    IDirectSoundBuffer_Stop(wmcda->dsBuf);
    SetEvent(wmcda->stopEvent);

    /* A design bug in native: the independent CD player called by the
     * MCI has no means to signal end of playing, therefore the MCI
     * notification is left hanging.  MCI_NOTIFY_SUPERSEDED will be
     * signaled by the next command that has MCI_NOTIFY set (or
     * MCI_NOTIFY_ABORTED for MCI_PLAY). */

    return 0;
}
Example #24
0
/*
	SNDDMA_InitDirect

	Direct-Sound support
*/
sndinitstat
SNDDMA_InitDirect (void)
{
	DSBUFFERDESC dsbuf;
	DSBCAPS     dsbcaps;
	DWORD       dwSize, dwWrite;
	DSCAPS      dscaps;
	WAVEFORMATEX format, pformat;
	HRESULT     hresult;
	int         reps;

	memset ((void *) &sn, 0, sizeof (sn));

	shm = &sn;

	shm->channels = 2;
	shm->samplebits = 16;
	shm->speed = 11025;

	memset (&format, 0, sizeof (format));
	format.wFormatTag = WAVE_FORMAT_PCM;
	format.nChannels = shm->channels;
	format.wBitsPerSample = shm->samplebits;
	format.nSamplesPerSec = shm->speed;
	format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
	format.cbSize = 0;
	format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;

	if (!hInstDS) {
		hInstDS = LoadLibrary ("dsound.dll");

		if (hInstDS == NULL) {
			Con_Printf ("Couldn't load dsound.dll\n");
			return SIS_FAILURE;
		}

		pDirectSoundCreate =
			(void *) GetProcAddress (hInstDS, "DirectSoundCreate");

		if (!pDirectSoundCreate) {
			Con_Printf ("Couldn't get DS proc addr\n");
			return SIS_FAILURE;
		}
	}

	while ((hresult = iDirectSoundCreate (NULL, &pDS, NULL)) != DS_OK) {
		if (hresult != DSERR_ALLOCATED) {
			Con_Printf ("DirectSound create failed\n");
			return SIS_FAILURE;
		}
		Con_Printf ("DirectSoundCreate failure\n"
					"  hardware already in use\n");
		return SIS_NOTAVAIL;
	}

	dscaps.dwSize = sizeof (dscaps);
	if (DS_OK != IDirectSound_GetCaps (pDS, &dscaps)) {
		Con_Printf ("Couldn't get DS caps\n");
	}

	if (dscaps.dwFlags & DSCAPS_EMULDRIVER) {
		Con_Printf ("No DirectSound driver installed\n");
		FreeSound ();
		return SIS_FAILURE;
	}

	if (DS_OK !=
		IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) {
		Con_Printf ("Set coop level failed\n");
		FreeSound ();
		return SIS_FAILURE;
	}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
	memset (&dsbuf, 0, sizeof (dsbuf));
	dsbuf.dwSize = sizeof (DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
	dsbuf.dwBufferBytes = 0;
	dsbuf.lpwfxFormat = NULL;

	memset (&dsbcaps, 0, sizeof (dsbcaps));
	dsbcaps.dwSize = sizeof (dsbcaps);
	primary_format_set = false;

	if (!COM_CheckParm ("-snoforceformat")) {
		if (DS_OK ==
			IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSPBuf, NULL)) {
			pformat = format;
	
			if (DS_OK != IDirectSoundBuffer_SetFormat (pDSPBuf, &pformat)) {
			} else primary_format_set = true;
		}
	}

	if (!primary_format_set || !COM_CheckParm ("-primarysound")) {
		// create the secondary buffer we'll actually work with
		memset (&dsbuf, 0, sizeof (dsbuf));
		dsbuf.dwSize = sizeof (DSBUFFERDESC);
		dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
		dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
		dsbuf.lpwfxFormat = &format;

		memset (&dsbcaps, 0, sizeof (dsbcaps));
		dsbcaps.dwSize = sizeof (dsbcaps);

		if (DS_OK !=
			IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSBuf, NULL)) {
			Con_Printf ("DS:CreateSoundBuffer Failed");
			FreeSound ();
			return SIS_FAILURE;
		}

		shm->channels = format.nChannels;
		shm->samplebits = format.wBitsPerSample;
		shm->speed = format.nSamplesPerSec;

		if (DS_OK != IDirectSound_GetCaps (pDSBuf, &dsbcaps)) {
			Con_Printf ("DS:GetCaps failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}
	} else {
		if (DS_OK !=
			IDirectSound_SetCooperativeLevel (pDS, mainwindow,
				  DSSCL_WRITEPRIMARY)) {
			Con_Printf ("Set coop level failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}

		if (DS_OK != IDirectSound_GetCaps (pDSPBuf, &dsbcaps)) {
			Con_Printf ("DS:GetCaps failed\n");
			return SIS_FAILURE;
		}

		pDSBuf = pDSPBuf;
	}

	// Make sure mixer is active
	IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);

	gSndBufSize = dsbcaps.dwBufferBytes;

// initialize the buffer
	reps = 0;

	while ((hresult = IDirectSoundBuffer_Lock (pDSBuf, 0, gSndBufSize,
			(LPVOID *) & lpData, &dwSize, NULL,NULL, 0)) != DS_OK) {
		if (hresult != DSERR_BUFFERLOST) {
			Con_Printf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}

		if (++reps > 10000) {
			Con_Printf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
			FreeSound ();
			return SIS_FAILURE;
		}

	}

	memset (lpData, 0, dwSize);
//      lpData[4] = lpData[5] = 0x7f;   // force a pop for debugging

	IDirectSoundBuffer_Unlock (pDSBuf, lpData, dwSize, NULL, 0);

	/* we don't want anyone to access the buffer directly w/o locking it
	   first. */
	lpData = NULL;

	IDirectSoundBuffer_Stop (pDSBuf);
	IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmstarttime.u.sample,
		&dwWrite);
	IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);

	shm->soundalive = true;
	shm->splitbuffer = false;
	shm->samples = gSndBufSize / (shm->samplebits / 8);
	shm->samplepos = 0;
	shm->submission_chunk = 1;
	shm->buffer = (unsigned char *) lpData;
	sample16 = (shm->samplebits / 8) - 1;

	dsound_init = true;

	return SIS_SUCCESS;
}
Example #25
0
static DWORD WINAPI bufferLoop(void *param)
{
  HANDLE handles[2] = { g_dsound.tickev, g_dsound.exitev };

  while (WaitForMultipleObjects(2, handles, FALSE, BUFFERLEN/3000) != WAIT_OBJECT_0 + 1) // while not exit
  {
    EnterCriticalSection(&g_dsound.crsec);

    void *buf1, *buf2;
    DWORD len1, len2;

    // fetch current buffer pos
    DWORD curpos;
    int nwrite = 0;
    for (;;)
    {
      HRESULT hr = IDirectSoundBuffer_GetCurrentPosition(g_dsound.sbuf, &curpos, NULL);
      if (hr == S_OK)
      {
        // find out how many bytes to write
        curpos &= ~31u;
        if (curpos == g_dsound.lastpos)
          goto done; // still the same

        nwrite = curpos - g_dsound.lastpos;
        if (nwrite < 0) {
          nwrite += BUFFERLEN;
          printf("positivizing nwrite\n");
        }
        printf("nwrite = %i\n", nwrite);

        hr = IDirectSoundBuffer_Lock(g_dsound.sbuf, g_dsound.lastpos, nwrite, &buf1, &len1, &buf2, &len2, 0);
      }

      if (hr == S_OK)
        break;
      else if (hr == DSERR_BUFFERLOST) {
        printf("buffer lost!\n");
        IDirectSoundBuffer_Restore(g_dsound.sbuf);
      } else {
        printf("something else went wrong\n");
        goto done;
      }
    }

    // we got the lock
    printf("got lock\n");
    g_dsound.lastpos = curpos;
    g_dsound.bufcnt += nwrite;

    // render to mix buffer
    g_dsound.callback(g_dsound.mixbuffer, nwrite / 2);

    // float->int, clamp
    //if (buf1)
    //  clamp(buf1, g_dsound.mixbuffer, len1/2);
    //if (buf2)
    //  clamp(buf2, g_dsound.mixbuffer + len1/2, len2/2);

    if (buf1) {
      printf("buf1: %d\n", len1);
      memcpy(buf1, g_dsound.mixbuffer, len1);
    }
    if (buf2) {
      printf("buf2: %d\n", len2);
      memcpy(buf2, g_dsound.mixbuffer + len1/2, len2);
    }

    HRESULT hr = IDirectSoundBuffer_Unlock(g_dsound.sbuf, buf1, len1, buf2, len2);
    if (!hr) {
      printf("unlock result: %i\n", hr);
    }

  done:
    LeaveCriticalSection(&g_dsound.crsec);
  }

  return 0;
}
Example #26
0
File: dsound.c Project: m64/PEG
static ALuint DSoundProc(ALvoid *ptr)
{
    ALCdevice *pDevice = (ALCdevice*)ptr;
    DSoundData *pData = (DSoundData*)pDevice->ExtraData;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    DWORD BufferSize;
    DWORD avail;
    HRESULT err;

    BufferSize  = pDevice->UpdateSize * DS_FRAGS *
                  aluBytesFromFormat(pDevice->Format) *
                  aluChannelsFromFormat(pDevice->Format);

    while(!pData->killNow)
    {
        // Get current play and write cursors
        IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+BufferSize) % BufferSize;

        if(avail == 0)
        {
            Sleep(1);
            continue;
        }

        // Lock output buffer
        WriteCnt1 = 0;
        WriteCnt2 = 0;
        err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);

        // If the buffer is lost, restore it, play and lock
        if(err == DSERR_BUFFERLOST)
        {
            err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
            if(SUCCEEDED(err))
                err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
        }

        // Successfully locked the output buffer
        if(SUCCEEDED(err))
        {
            // If we have an active context, mix data directly into output buffer otherwise fill with silence
            SuspendContext(NULL);
            aluMixData(pDevice->Context, WritePtr1, WriteCnt1, pDevice->Format);
            aluMixData(pDevice->Context, WritePtr2, WriteCnt2, pDevice->Format);
            ProcessContext(NULL);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
            AL_PRINT("Buffer lock error: %#lx\n", err);

        // Update old write cursor location
        LastCursor += WriteCnt1+WriteCnt2;
        LastCursor %= BufferSize;
    }

    return 0;
}
Example #27
0
static void DirectSound_update_audio(void)
{
    HRESULT hr;
    int next_voice_pos;

    VOID *area1,*area2;
    DWORD len_area1,len_area2;

    if (dsb == NULL || new_sound_data == FALSE)
        return;

	profiler_mark(PROFILER_MIXER);
    
    next_voice_pos = voice_pos + stream_cache_len*sizeof(INT16)*stereo_factor;
    if (next_voice_pos >= buffer_length)
        next_voice_pos -= buffer_length;

    if (Display_Throttled()) /* sync with audio only when speed throttling is not turned off */
    {
        profiler_mark(PROFILER_IDLE);
        for (;;)
        {
            LONG curpos;
            LONG writepos;
          
            IDirectSoundBuffer_GetCurrentPosition(dsb,&curpos,&writepos);
            if (voice_pos < next_voice_pos)
            {
                if (curpos < voice_pos || curpos >= next_voice_pos)
                    break;
            }
            else
            {
                if (curpos < voice_pos && curpos >= next_voice_pos)
                    break;
            }
        }
        profiler_mark(PROFILER_END);
    }

    hr = IDirectSoundBuffer_Lock(dsb,
                                 voice_pos,
                                 stream_cache_len * sizeof(INT16) * stereo_factor,
                                 &area1, &len_area1,
                                 &area2, &len_area2,
                                 0);
    if (FAILED(hr))
    {
        ErrorMsg("Unable to lock secondary sound buffer: %s",DirectXDecodeError(hr));
    }
    else
    {
        memcpy(area1, stream_cache_data, len_area1);
        memcpy(area2, ((byte *)stream_cache_data) + len_area1, len_area2);
       
        hr = IDirectSoundBuffer_Unlock(dsb,area1,len_area1,area2,len_area2);
        if (FAILED(hr))
            ErrorMsg("Unable to unlock secondary sound buffer: %s",DirectXDecodeError(hr));
    }

    voice_pos = next_voice_pos;

	profiler_mark(PROFILER_END);

    new_sound_data = FALSE;
}