Example #1
0
static Uint8 *
DSOUND_GetDeviceBuf(_THIS)
{
    DWORD cursor = 0;
    DWORD junk = 0;
    HRESULT result = DS_OK;
    DWORD rawlen = 0;

    /* Figure out which blocks to fill next */
    this->hidden->locked_buf = NULL;
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                   &junk, &cursor);
    if (result == DSERR_BUFFERLOST) {
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                       &junk, &cursor);
    }
    if (result != DS_OK) {
        SetDSerror("DirectSound GetCurrentPosition", result);
        return (NULL);
    }
    cursor /= this->hidden->mixlen;
#ifdef DEBUG_SOUND
    /* Detect audio dropouts */
    {
        DWORD spot = cursor;
        if (spot < this->hidden->lastchunk) {
            spot += this->hidden->num_buffers;
        }
        if (spot > this->hidden->lastchunk + 1) {
            fprintf(stderr, "Audio dropout, missed %d fragments\n",
                    (spot - (this->hidden->lastchunk + 1)));
        }
    }
#endif
    this->hidden->lastchunk = cursor;
    cursor = (cursor + 1) % this->hidden->num_buffers;
    cursor *= this->hidden->mixlen;

    /* Lock the audio buffer */
    result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
                                     this->hidden->mixlen,
                                     (LPVOID *) & this->hidden->locked_buf,
                                     &rawlen, NULL, &junk, 0);
    if (result == DSERR_BUFFERLOST) {
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
                                         this->hidden->mixlen,
                                         (LPVOID *) & this->
                                         hidden->locked_buf, &rawlen, NULL,
                                         &junk, 0);
    }
    if (result != DS_OK) {
        SetDSerror("DirectSound Lock", result);
        return (NULL);
    }
    return (this->hidden->locked_buf);
}
Example #2
0
static void
DSOUND_WaitDevice(_THIS)
{
    DWORD status = 0;
    DWORD cursor = 0;
    DWORD junk = 0;
    HRESULT result = DS_OK;

    /* Semi-busy wait, since we have no way of getting play notification
       on a primary mixing buffer located in hardware (DirectX 5.0)
     */
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                   &junk, &cursor);
    if (result != DS_OK) {
        if (result == DSERR_BUFFERLOST) {
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        }
#ifdef DEBUG_SOUND
        SetDSerror("DirectSound GetCurrentPosition", result);
#endif
        return;
    }

    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
        /* FIXME: find out how much time is left and sleep that long */
        SDL_Delay(1);

        /* Try to restore a lost sound buffer */
        IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
        if ((status & DSBSTATUS_BUFFERLOST)) {
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
            IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
            if ((status & DSBSTATUS_BUFFERLOST)) {
                break;
            }
        }
        if (!(status & DSBSTATUS_PLAYING)) {
            result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
                                             DSBPLAY_LOOPING);
            if (result == DS_OK) {
                continue;
            }
#ifdef DEBUG_SOUND
            SetDSerror("DirectSound Play", result);
#endif
            return;
        }

        /* Find out where we are playing */
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                       &junk, &cursor);
        if (result != DS_OK) {
            SetDSerror("DirectSound GetCurrentPosition", result);
            return;
        }
    }
}
Example #3
0
static void DX5_WaitAudio_BusyWait(_THIS)
{
	DWORD status;
	DWORD cursor, junk;
	HRESULT result;

	/* Semi-busy wait, since we have no way of getting play notification
	   on a primary mixing buffer located in hardware (DirectX 5.0)
	*/
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk);
	if ( result != DS_OK ) {
		if ( result == DSERR_BUFFERLOST ) {
			IDirectSoundBuffer_Restore(mixbuf);
		}
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound GetCurrentPosition", result);
#endif
		return;
	}
	cursor /= mixlen;

	while ( cursor == playing ) {
		/* FIXME: find out how much time is left and sleep that long */
		SDL_Delay(10);

		/* Try to restore a lost sound buffer */
		IDirectSoundBuffer_GetStatus(mixbuf, &status);
		if ( (status&DSBSTATUS_BUFFERLOST) ) {
			IDirectSoundBuffer_Restore(mixbuf);
			IDirectSoundBuffer_GetStatus(mixbuf, &status);
			if ( (status&DSBSTATUS_BUFFERLOST) ) {
				break;
			}
		}
		if ( ! (status&DSBSTATUS_PLAYING) ) {
			result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
			if ( result == DS_OK ) {
				continue;
			}
#ifdef DEBUG_SOUND
			SetDSerror("DirectSound Play", result);
#endif
			return;
		}

		/* Find out where we are playing */
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&cursor, &junk);
		if ( result != DS_OK ) {
			SetDSerror("DirectSound GetCurrentPosition", result);
			return;
		}
		cursor /= mixlen;
	}
}
Example #4
0
static Uint8 *DX5_GetAudioBuf(_THIS)
{
	DWORD   cursor, junk;
	HRESULT result;
	DWORD   rawlen;

	/* Figure out which blocks to fill next */
	locked_buf = NULL;
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&junk, &cursor);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound GetCurrentPosition", result);
		return(NULL);
	}
	cursor /= mixlen;
#ifdef DEBUG_SOUND
	/* Detect audio dropouts */
	{ DWORD spot = cursor;
	  if ( spot < lastchunk ) {
	    spot += NUM_BUFFERS;
	  }
	  if ( spot > lastchunk+1 ) {
	    fprintf(stderr, "Audio dropout, missed %d fragments\n",
	            (spot - (lastchunk+1)));
	  }
	}
#endif
	lastchunk = cursor;
	cursor = (cursor+1)%NUM_BUFFERS;
	cursor *= mixlen;

	/* Lock the audio buffer */
	result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound Lock", result);
		return(NULL);
	}
	return(locked_buf);
}
Example #5
0
static void DX6_WaitAudio_EventWait(_THIS)
{
	DWORD status;
	HRESULT result;

	/* Try to restore a lost sound buffer */
	IDirectSoundBuffer_GetStatus(mixbuf, &status);
	if ( (status&DSBSTATUS_BUFFERLOST) ) {
		IDirectSoundBuffer_Restore(mixbuf);
		IDirectSoundBuffer_GetStatus(mixbuf, &status);
		if ( (status&DSBSTATUS_BUFFERLOST) ) {
			return;
		}
	}
	if ( ! (status&DSBSTATUS_PLAYING) ) {
		result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
		if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
			SetDSerror("DirectSound Play", result);
#endif
			return;
		}
	}
	WaitForSingleObject(audio_event, INFINITE);
}
static int
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    HRESULT result;
    SDL_bool valid_format = SDL_FALSE;
    SDL_bool tried_format = SDL_FALSE;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    LPGUID guid = (LPGUID) handle;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Open the audio device */
    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
    if (result != DS_OK) {
        DSOUND_CloseDevice(this);
        return SetDSerror("DirectSoundCreate", result);
    }

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            tried_format = SDL_TRUE;
            this->spec.format = test_format;
            this->hidden->num_buffers = CreateSecondary(this, NULL);
            if (this->hidden->num_buffers > 0) {
                valid_format = SDL_TRUE;
            }
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        DSOUND_CloseDevice(this);
        if (tried_format) {
            return -1;  /* CreateSecondary() should have called SDL_SetError(). */
        }
        return SDL_SetError("DirectSound: Unsupported audio format");
    }

    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
    this->hidden->mixlen = this->spec.size;

    return 0;                   /* good to go. */
}
Example #7
0
/* This function tries to create a capture buffer, and returns the
   number of audio chunks available in the created buffer. This is for
   capture devices, not playback.
*/
static int
CreateCaptureBuffer(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
{
    LPDIRECTSOUNDCAPTURE capture = this->hidden->capture;
    LPDIRECTSOUNDCAPTUREBUFFER *capturebuf = &this->hidden->capturebuf;
    DSCBUFFERDESC format;
//    DWORD junk, cursor;
    HRESULT result;

    SDL_zero(format);
    format.dwSize = sizeof (format);
    format.dwFlags = DSCBCAPS_WAVEMAPPED;
    format.dwBufferBytes = bufsize;
    format.lpwfxFormat = wfmt;

    result = IDirectSoundCapture_CreateCaptureBuffer(capture, &format, capturebuf, NULL);
    if (result != DS_OK) {
        return SetDSerror("DirectSound CreateCaptureBuffer", result);
    }

    result = IDirectSoundCaptureBuffer_Start(*capturebuf, DSCBSTART_LOOPING);
    if (result != DS_OK) {
        IDirectSoundCaptureBuffer_Release(*capturebuf);
        return SetDSerror("DirectSound Start", result);
    }

#if 0
    /* presumably this starts at zero, but just in case... */
    result = IDirectSoundCaptureBuffer_GetCurrentPosition(*capturebuf, &junk, &cursor);
    if (result != DS_OK) {
        IDirectSoundCaptureBuffer_Stop(*capturebuf);
        IDirectSoundCaptureBuffer_Release(*capturebuf);
        return SetDSerror("DirectSound GetCurrentPosition", result);
    }

    this->hidden->lastchunk = cursor / this->spec.size;
#endif

    return 0;
}
Example #8
0
static Uint8 *DX5_GetAudioBuf(_THIS)
{
	DWORD   cursor, junk;
	HRESULT result;
	DWORD   rawlen;

	/* Figure out which blocks to fill next */
	locked_buf = NULL;
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&cursor, &junk);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound GetCurrentPosition", result);
		return(NULL);
	}
	cursor /= mixlen;
	playing = cursor;
	cursor = (cursor+1)%NUM_BUFFERS;
	cursor *= mixlen;

	/* Lock the audio buffer */
	result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound Lock", result);
		return(NULL);
	}
	return(locked_buf);
}
Example #9
0
/* This function tries to create a secondary audio buffer, and returns the
   number of audio chunks available in the created buffer. This is for
   playback devices, not capture.
*/
static int
CreateSecondary(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
{
    LPDIRECTSOUND sndObj = this->hidden->sound;
    LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
    HRESULT result = DS_OK;
    DSBUFFERDESC format;
    LPVOID pvAudioPtr1, pvAudioPtr2;
    DWORD dwAudioBytes1, dwAudioBytes2;

    /* Try to create the secondary buffer */
    SDL_zero(format);
    format.dwSize = sizeof(format);
    format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
    format.dwFlags |= DSBCAPS_GLOBALFOCUS;
    format.dwBufferBytes = bufsize;
    format.lpwfxFormat = wfmt;
    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
    if (result != DS_OK) {
        return SetDSerror("DirectSound CreateSoundBuffer", result);
    }
    IDirectSoundBuffer_SetFormat(*sndbuf, wfmt);

    /* Silence the initial audio buffer */
    result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
                                     (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
                                     (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
                                     DSBLOCK_ENTIREBUFFER);
    if (result == DS_OK) {
        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
        IDirectSoundBuffer_Unlock(*sndbuf,
                                  (LPVOID) pvAudioPtr1, dwAudioBytes1,
                                  (LPVOID) pvAudioPtr2, dwAudioBytes2);
    }

    /* We're ready to go */
    return 0;
}
Example #10
0
static int
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
{
    HRESULT result;
    WAVEFORMATEX waveformat;
    int valid_format = 0;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    FindDevGUIDData devguid;
    LPGUID guid = NULL;

    if (devname != NULL) {
        devguid.found = 0;
        devguid.devname = devname;
        if (iscapture)
            pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
        else
            pDirectSoundEnumerateW(FindDevGUID, &devguid);

        if (!devguid.found) {
            SDL_SetError("DirectSound: Requested device not found");
            return 0;
        }
        guid = &devguid.guid;
    }

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
            this->spec.format = test_format;
            valid_format = 1;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        DSOUND_CloseDevice(this);
        SDL_SetError("DirectSound: Unsupported audio format");
        return 0;
    }

    SDL_memset(&waveformat, 0, sizeof(waveformat));
    waveformat.wFormatTag = WAVE_FORMAT_PCM;
    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
    waveformat.nChannels = this->spec.channels;
    waveformat.nSamplesPerSec = this->spec.freq;
    waveformat.nBlockAlign =
        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
    waveformat.nAvgBytesPerSec =
        waveformat.nSamplesPerSec * waveformat.nBlockAlign;

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* Open the audio device */
    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
    if (result != DS_OK) {
        DSOUND_CloseDevice(this);
        SetDSerror("DirectSoundCreate", result);
        return 0;
    }

    /* Create the audio buffer to which we write */
    this->hidden->num_buffers = CreateSecondary(this, NULL, &waveformat);
    if (this->hidden->num_buffers < 0) {
        DSOUND_CloseDevice(this);
        return 0;
    }

    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
    this->hidden->mixlen = this->spec.size;

    return 1;                   /* good to go. */
}
Example #11
0
/* This function tries to create a secondary audio buffer, and returns the
   number of audio chunks available in the created buffer.
*/
static int
CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
{
    LPDIRECTSOUND sndObj = this->hidden->sound;
    LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
    Uint32 chunksize = this->spec.size;
    const int numchunks = 8;
    HRESULT result = DS_OK;
    DSBUFFERDESC format;
    LPVOID pvAudioPtr1, pvAudioPtr2;
    DWORD dwAudioBytes1, dwAudioBytes2;

    /* Try to set primary mixing privileges */
    if (focus) {
        result = IDirectSound_SetCooperativeLevel(sndObj,
                                                  focus, DSSCL_PRIORITY);
    } else {
        result = IDirectSound_SetCooperativeLevel(sndObj,
                                                  GetDesktopWindow(),
                                                  DSSCL_NORMAL);
    }
    if (result != DS_OK) {
        SetDSerror("DirectSound SetCooperativeLevel", result);
        return (-1);
    }

    /* Try to create the secondary buffer */
    SDL_memset(&format, 0, sizeof(format));
    format.dwSize = sizeof(format);
    format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
    if (!focus) {
        format.dwFlags |= DSBCAPS_GLOBALFOCUS;
    } else {
        format.dwFlags |= DSBCAPS_STICKYFOCUS;
    }
    format.dwBufferBytes = numchunks * chunksize;
    if ((format.dwBufferBytes < DSBSIZE_MIN) ||
        (format.dwBufferBytes > DSBSIZE_MAX)) {
        SDL_SetError("Sound buffer size must be between %d and %d",
                     DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
        return (-1);
    }
    format.dwReserved = 0;
    format.lpwfxFormat = wavefmt;
    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
    if (result != DS_OK) {
        SetDSerror("DirectSound CreateSoundBuffer", result);
        return (-1);
    }
    IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);

    /* Silence the initial audio buffer */
    result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
                                     (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
                                     (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
                                     DSBLOCK_ENTIREBUFFER);
    if (result == DS_OK) {
        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
        IDirectSoundBuffer_Unlock(*sndbuf,
                                  (LPVOID) pvAudioPtr1, dwAudioBytes1,
                                  (LPVOID) pvAudioPtr2, dwAudioBytes2);
    }

    /* We're ready to go */
    return (numchunks);
}
Example #12
0
static int
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    const DWORD numchunks = 8;
    HRESULT result;
    SDL_bool valid_format = SDL_FALSE;
    SDL_bool tried_format = SDL_FALSE;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    LPGUID guid = (LPGUID) handle;
	DWORD bufsize;
	
    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_zerop(this->hidden);

    /* Open the audio device */
    if (iscapture) {
        result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture, NULL);
        if (result != DS_OK) {
            return SetDSerror("DirectSoundCaptureCreate8", result);
        }
    } else {
        result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
        if (result != DS_OK) {
            return SetDSerror("DirectSoundCreate8", result);
        }
        result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
                                                  GetDesktopWindow(),
                                                  DSSCL_NORMAL);
        if (result != DS_OK) {
            return SetDSerror("DirectSound SetCooperativeLevel", result);
        }
    }

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            tried_format = SDL_TRUE;

            this->spec.format = test_format;

            /* Update the fragment size as size in bytes */
            SDL_CalculateAudioSpec(&this->spec);

            bufsize = numchunks * this->spec.size;
            if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) {
                SDL_SetError("Sound buffer size must be between %d and %d",
                             (DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks,
                             DSBSIZE_MAX / numchunks);
            } else {
                int rc;
				WAVEFORMATEX wfmt;
                SDL_zero(wfmt);
                if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
                    wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
                } else {
                    wfmt.wFormatTag = WAVE_FORMAT_PCM;
                }

                wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
                wfmt.nChannels = this->spec.channels;
                wfmt.nSamplesPerSec = this->spec.freq;
                wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
                wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;

                rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
                if (rc == 0) {
                    this->hidden->num_buffers = numchunks;
                    valid_format = SDL_TRUE;
                }
            }
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        if (tried_format) {
            return -1;  /* CreateSecondary() should have called SDL_SetError(). */
        }
        return SDL_SetError("DirectSound: Unsupported audio format");
    }

    /* Playback buffers will auto-start playing in DSOUND_WaitDevice() */

    return 0;                   /* good to go. */
}
Example #13
0
static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	HRESULT      result;
	WAVEFORMATEX waveformat;

	/* Set basic WAVE format parameters */
	memset(&waveformat, 0, sizeof(waveformat));
	waveformat.wFormatTag = WAVE_FORMAT_PCM;

	/* Determine the audio parameters from the AudioSpec */
	switch ( spec->format & 0xFF ) {
		case 8:
			/* Unsigned 8 bit audio data */
			spec->format = AUDIO_U8;
			silence = 0x80;
			waveformat.wBitsPerSample = 8;
			break;
		case 16:
			/* Signed 16 bit audio data */
			spec->format = AUDIO_S16;
			silence = 0x00;
			waveformat.wBitsPerSample = 16;
			break;
		default:
			SDL_SetError("Unsupported audio format");
			return(-1);
	}
	waveformat.nChannels = spec->channels;
	waveformat.nSamplesPerSec = spec->freq;
	waveformat.nBlockAlign =
		waveformat.nChannels * (waveformat.wBitsPerSample/8);
	waveformat.nAvgBytesPerSec = 
		waveformat.nSamplesPerSec * waveformat.nBlockAlign;

	/* Update the fragment size as size in bytes */
	SDL_CalculateAudioSpec(spec);

	/* Open the audio device */
	result = DSoundCreate(NULL, &sound, NULL);
	if ( result != DS_OK ) {
		SetDSerror("DirectSoundCreate", result);
		return(-1);
	}

	/* Create the audio buffer to which we write */
	NUM_BUFFERS = -1;
#ifdef USE_PRIMARY_BUFFER
	if ( mainwin ) {
		NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf,
						&waveformat, spec->size);
	}
#endif /* USE_PRIMARY_BUFFER */
	if ( NUM_BUFFERS < 0 ) {
		NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf,
						&waveformat, spec->size);
		if ( NUM_BUFFERS < 0 ) {
			return(-1);
		}
#ifdef DEBUG_SOUND
		fprintf(stderr, "Using secondary audio buffer\n");
#endif
	}
#ifdef DEBUG_SOUND
	else
		fprintf(stderr, "Using primary audio buffer\n");
#endif

	/* The buffer will auto-start playing in DX5_WaitAudio() */
	playing = 0;
	mixlen = spec->size;

#ifdef USE_POSITION_NOTIFY
	/* See if we can use DirectX 6 event notification */
	if ( CreateAudioEvent(this) == 0 ) {
		this->WaitAudio = DX6_WaitAudio_EventWait;
	} else {
		this->WaitAudio = DX5_WaitAudio_BusyWait;
	}
#endif
	return(0);
}
Example #14
0
/* This function tries to create a secondary audio buffer, and returns the
   number of audio chunks available in the created buffer.
*/
static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus,
	LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize)
{
	const int numchunks = 2;
	HRESULT result;
	DSBUFFERDESC format;
	LPVOID pvAudioPtr1, pvAudioPtr2;
	DWORD  dwAudioBytes1, dwAudioBytes2;

	/* Try to set primary mixing privileges */
	if ( focus ) {
		result = IDirectSound_SetCooperativeLevel(sndObj,
					focus, DSSCL_PRIORITY);
	} else {
		result = IDirectSound_SetCooperativeLevel(sndObj,
					GetDesktopWindow(), DSSCL_NORMAL);
	}
	if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound SetCooperativeLevel", result);
#endif
		return(-1);
	}

	/* Try to create the secondary buffer */
	memset(&format, 0, sizeof(format));
	format.dwSize = sizeof(format);
	format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
#ifdef USE_POSITION_NOTIFY
	format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
#endif
	if ( ! focus ) {
		format.dwFlags |= DSBCAPS_GLOBALFOCUS;
	} else {
		format.dwFlags |= DSBCAPS_STICKYFOCUS;
	}
	format.dwBufferBytes = numchunks*chunksize;
	if ( (format.dwBufferBytes < DSBSIZE_MIN) ||
	     (format.dwBufferBytes > DSBSIZE_MAX) ) {
		SDL_SetError("Sound buffer size must be between %d and %d",
				DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks);
		return(-1);
	}
	format.dwReserved = 0;
	format.lpwfxFormat = wavefmt;
	result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
	if ( result != DS_OK ) {
		SetDSerror("DirectSound CreateSoundBuffer", result);
		return(-1);
	}
	IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);

	/* Silence the initial audio buffer */
	result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
	                                 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1,
	                                 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2,
	                                 DSBLOCK_ENTIREBUFFER);
	if ( result == DS_OK ) {
		if ( wavefmt->wBitsPerSample == 8 ) {
			memset(pvAudioPtr1, 0x80, dwAudioBytes1);
		} else {
			memset(pvAudioPtr1, 0x00, dwAudioBytes1);
		}
		IDirectSoundBuffer_Unlock(*sndbuf,
		                          (LPVOID)pvAudioPtr1, dwAudioBytes1,
		                          (LPVOID)pvAudioPtr2, dwAudioBytes2);
	}

	/* We're ready to go */
	return(numchunks);
}
Example #15
0
/* This function tries to create a primary audio buffer, and returns the
   number of audio chunks available in the created buffer.
*/
static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, 
	LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize)
{
	HRESULT result;
	DSBUFFERDESC format;
	DSBCAPS caps;
	int numchunks;

	/* Try to set primary mixing privileges */
	result = IDirectSound_SetCooperativeLevel(sndObj, focus,
							DSSCL_WRITEPRIMARY);
	if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound SetCooperativeLevel", result);
#endif
		return(-1);
	}

	/* Try to create the primary buffer */
	memset(&format, 0, sizeof(format));
	format.dwSize = sizeof(format);
	format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2);
	format.dwFlags |= DSBCAPS_STICKYFOCUS;
#ifdef USE_POSITION_NOTIFY
	format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
#endif
	result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
	if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound CreateSoundBuffer", result);
#endif
		return(-1);
	}

	/* Check the size of the fragment buffer */
	memset(&caps, 0, sizeof(caps));
	caps.dwSize = sizeof(caps);
	result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps);
	if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound GetCaps", result);
#endif
		IDirectSoundBuffer_Release(*sndbuf);
		return(-1);
	}
	if ( (chunksize > caps.dwBufferBytes) ||
				((caps.dwBufferBytes%chunksize) != 0) ) {
		/* The primary buffer size is not a multiple of 'chunksize'
		   -- this hopefully doesn't happen when 'chunksize' is a 
		      power of 2.
		*/
		IDirectSoundBuffer_Release(*sndbuf);
		SDL_SetError(
"Primary buffer size is: %d, cannot break it into chunks of %d bytes\n",
					caps.dwBufferBytes, chunksize);
		return(-1);
	}
	numchunks = (caps.dwBufferBytes/chunksize);

	/* Set the primary audio format */
	result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
	if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound SetFormat", result);
#endif
		IDirectSoundBuffer_Release(*sndbuf);
		return(-1);
	}
	return(numchunks);
}
Example #16
0
/* This function tries to create a secondary audio buffer, and returns the
   number of audio chunks available in the created buffer.
*/
static int
CreateSecondary(_THIS, HWND focus)
{
    LPDIRECTSOUND sndObj = this->hidden->sound;
    LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
    Uint32 chunksize = this->spec.size;
    const int numchunks = 8;
    HRESULT result = DS_OK;
    DSBUFFERDESC format;
    LPVOID pvAudioPtr1, pvAudioPtr2;
    DWORD dwAudioBytes1, dwAudioBytes2;
    WAVEFORMATEX wfmt;

    SDL_zero(wfmt);

    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
        wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    } else {
        wfmt.wFormatTag = WAVE_FORMAT_PCM;
    }

    wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
    wfmt.nChannels = this->spec.channels;
    wfmt.nSamplesPerSec = this->spec.freq;
    wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
    wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* Try to set primary mixing privileges */
    if (focus) {
        result = IDirectSound_SetCooperativeLevel(sndObj,
                                                  focus, DSSCL_PRIORITY);
    } else {
        result = IDirectSound_SetCooperativeLevel(sndObj,
                                                  GetDesktopWindow(),
                                                  DSSCL_NORMAL);
    }
    if (result != DS_OK) {
        return SetDSerror("DirectSound SetCooperativeLevel", result);
    }

    /* Try to create the secondary buffer */
    SDL_zero(format);
    format.dwSize = sizeof(format);
    format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
    if (!focus) {
        format.dwFlags |= DSBCAPS_GLOBALFOCUS;
    } else {
        format.dwFlags |= DSBCAPS_STICKYFOCUS;
    }
    format.dwBufferBytes = numchunks * chunksize;
    if ((format.dwBufferBytes < DSBSIZE_MIN) ||
        (format.dwBufferBytes > DSBSIZE_MAX)) {
        return SDL_SetError("Sound buffer size must be between %d and %d",
                            DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
    }
    format.dwReserved = 0;
    format.lpwfxFormat = &wfmt;
    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
    if (result != DS_OK) {
        return SetDSerror("DirectSound CreateSoundBuffer", result);
    }
    IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);

    /* Silence the initial audio buffer */
    result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
                                     (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
                                     (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
                                     DSBLOCK_ENTIREBUFFER);
    if (result == DS_OK) {
        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
        IDirectSoundBuffer_Unlock(*sndbuf,
                                  (LPVOID) pvAudioPtr1, dwAudioBytes1,
                                  (LPVOID) pvAudioPtr2, dwAudioBytes2);
    }

    /* We're ready to go */
    return (numchunks);
}