mirror of https://github.com/PCSX2/pcsx2.git
269 lines
7.8 KiB
C
269 lines
7.8 KiB
C
|
/***************************************************************************
|
||
|
dsound.c - description
|
||
|
-------------------
|
||
|
begin : Wed May 15 2002
|
||
|
copyright : (C) 2002 by Pete Bernert
|
||
|
email : BlackDove@addcom.de
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. See also the license.txt file for *
|
||
|
* additional informations. *
|
||
|
* *
|
||
|
***************************************************************************/
|
||
|
|
||
|
//*************************************************************************//
|
||
|
// History of changes:
|
||
|
//
|
||
|
// 2005/08/29 - Pete
|
||
|
// - changed to 48Khz output
|
||
|
//
|
||
|
// 2003/01/12 - Pete
|
||
|
// - added recording funcs
|
||
|
//
|
||
|
// 2002/05/15 - Pete
|
||
|
// - generic cleanup for the Peops release
|
||
|
//
|
||
|
//*************************************************************************//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#define _IN_DSOUND
|
||
|
|
||
|
#include "externals.h"
|
||
|
|
||
|
#ifdef _WINDOWS
|
||
|
#define _LPCWAVEFORMATEX_DEFINED
|
||
|
#include "dsound.h"
|
||
|
|
||
|
#include "record.h"
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// dsound globals
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
LPDIRECTSOUND lpDS;
|
||
|
LPDIRECTSOUNDBUFFER lpDSBPRIMARY = NULL;
|
||
|
LPDIRECTSOUNDBUFFER lpDSBSECONDARY1 = NULL;
|
||
|
LPDIRECTSOUNDBUFFER lpDSBSECONDARY2 = NULL;
|
||
|
DSBUFFERDESC dsbd;
|
||
|
DSBUFFERDESC dsbdesc;
|
||
|
DSCAPS dscaps;
|
||
|
DSBCAPS dsbcaps;
|
||
|
|
||
|
unsigned long LastWrite=0xffffffff;
|
||
|
unsigned long LastWriteS=0xffffffff;
|
||
|
unsigned long LastPlay=0;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// SETUP SOUND
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void SetupSound(void)
|
||
|
{
|
||
|
HRESULT dsval;WAVEFORMATEX pcmwf;
|
||
|
|
||
|
dsval = DirectSoundCreate(NULL,&lpDS,NULL);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain,"DirectSoundCreate!","Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(DS_OK!=IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_PRIORITY))
|
||
|
{
|
||
|
if(DS_OK!=IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_NORMAL))
|
||
|
{
|
||
|
MessageBox(hWMain,"SetCooperativeLevel!","Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset(&dsbd,0,sizeof(DSBUFFERDESC));
|
||
|
dsbd.dwSize = sizeof(DSBUFFERDESC); // NT4 hack! sizeof(dsbd);
|
||
|
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||
|
dsbd.dwBufferBytes = 0;
|
||
|
dsbd.lpwfxFormat = NULL;
|
||
|
|
||
|
dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbd,&lpDSBPRIMARY,NULL);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain, "CreateSoundBuffer (Primary)", "Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
|
||
|
pcmwf.wFormatTag = WAVE_FORMAT_PCM;
|
||
|
|
||
|
pcmwf.nChannels = 2;
|
||
|
pcmwf.nBlockAlign = 4;
|
||
|
|
||
|
pcmwf.nSamplesPerSec = 48000;
|
||
|
|
||
|
pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
|
||
|
pcmwf.wBitsPerSample = 16;
|
||
|
|
||
|
dsval=IDirectSoundBuffer_SetFormat(lpDSBPRIMARY,&pcmwf);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain, "SetFormat!", "Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dscaps.dwSize = sizeof(DSCAPS);
|
||
|
dsbcaps.dwSize = sizeof(DSBCAPS);
|
||
|
IDirectSound_GetCaps(lpDS,&dscaps);
|
||
|
IDirectSoundBuffer_GetCaps(lpDSBPRIMARY,&dsbcaps);
|
||
|
|
||
|
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
||
|
dsbdesc.dwSize = sizeof(DSBUFFERDESC); // NT4 hack! sizeof(DSBUFFERDESC);
|
||
|
dsbdesc.dwFlags = DSBCAPS_LOCHARDWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
|
||
|
dsbdesc.dwBufferBytes = SOUNDSIZE;
|
||
|
dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
|
||
|
|
||
|
dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
dsbdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
|
||
|
dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain,"CreateSoundBuffer (Secondary1)", "Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
dsval=IDirectSoundBuffer_Play(lpDSBPRIMARY,0,0,DSBPLAY_LOOPING);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain,"Play (Primary)","Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dsval=IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING);
|
||
|
if(dsval!=DS_OK)
|
||
|
{
|
||
|
MessageBox(hWMain,"Play (Secondary1)","Error",MB_OK);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// REMOVE SOUND
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void RemoveSound(void)
|
||
|
{
|
||
|
int iRes;
|
||
|
|
||
|
if(iDoRecord) RecordStop();
|
||
|
|
||
|
if(lpDSBSECONDARY1!=NULL)
|
||
|
{
|
||
|
IDirectSoundBuffer_Stop(lpDSBSECONDARY1);
|
||
|
iRes=IDirectSoundBuffer_Release(lpDSBSECONDARY1);
|
||
|
// FF says such a loop is bad... Demo says it's good... Pete doesn't care
|
||
|
while(iRes!=0) iRes=IDirectSoundBuffer_Release(lpDSBSECONDARY1);
|
||
|
lpDSBSECONDARY1=NULL;
|
||
|
}
|
||
|
|
||
|
if(lpDSBPRIMARY!=NULL)
|
||
|
{
|
||
|
IDirectSoundBuffer_Stop(lpDSBPRIMARY);
|
||
|
iRes=IDirectSoundBuffer_Release(lpDSBPRIMARY);
|
||
|
// FF says such a loop is bad... Demo says it's good... Pete doesn't care
|
||
|
while(iRes!=0) iRes=IDirectSoundBuffer_Release(lpDSBPRIMARY);
|
||
|
lpDSBPRIMARY=NULL;
|
||
|
}
|
||
|
|
||
|
if(lpDS!=NULL)
|
||
|
{
|
||
|
iRes=IDirectSound_Release(lpDS);
|
||
|
// FF says such a loop is bad... Demo says it's good... Pete doesn't care
|
||
|
while(iRes!=0) iRes=IDirectSound_Release(lpDS);
|
||
|
lpDS=NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// GET BYTES BUFFERED
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
unsigned long SoundGetBytesBuffered(void)
|
||
|
{
|
||
|
unsigned long cplay,cwrite;
|
||
|
|
||
|
if(LastWrite==0xffffffff) return 0;
|
||
|
|
||
|
IDirectSoundBuffer_GetCurrentPosition(lpDSBSECONDARY1,&cplay,&cwrite);
|
||
|
|
||
|
if(cplay>SOUNDSIZE) return SOUNDSIZE;
|
||
|
|
||
|
if(cplay<LastWrite) return LastWrite-cplay;
|
||
|
return (SOUNDSIZE-cplay)+LastWrite;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// FEED SOUND DATA
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void SoundFeedVoiceData(unsigned char* pSound,long lBytes)
|
||
|
{
|
||
|
LPVOID lpvPtr1, lpvPtr2;
|
||
|
unsigned long dwBytes1,dwBytes2;
|
||
|
unsigned long *lpSS, *lpSD;
|
||
|
unsigned long dw,cplay,cwrite;
|
||
|
HRESULT hr;
|
||
|
unsigned long status;
|
||
|
|
||
|
if(iDoRecord) RecordBuffer(pSound,lBytes);
|
||
|
|
||
|
IDirectSoundBuffer_GetStatus(lpDSBSECONDARY1,&status);
|
||
|
if(status&DSBSTATUS_BUFFERLOST)
|
||
|
{
|
||
|
if(IDirectSoundBuffer_Restore(lpDSBSECONDARY1)!=DS_OK) return;
|
||
|
IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING);
|
||
|
}
|
||
|
|
||
|
IDirectSoundBuffer_GetCurrentPosition(lpDSBSECONDARY1,&cplay,&cwrite);
|
||
|
|
||
|
if(LastWrite==0xffffffff) LastWrite=cwrite;
|
||
|
|
||
|
hr=IDirectSoundBuffer_Lock(lpDSBSECONDARY1,LastWrite,lBytes,
|
||
|
&lpvPtr1, &dwBytes1,
|
||
|
&lpvPtr2, &dwBytes2,
|
||
|
0);
|
||
|
|
||
|
if(hr!=DS_OK) {LastWrite=0xffffffff;return;}
|
||
|
|
||
|
lpSD=(unsigned long *)lpvPtr1;
|
||
|
dw=dwBytes1>>2;
|
||
|
|
||
|
lpSS=(unsigned long *)pSound;
|
||
|
while(dw) {*lpSD++=*lpSS++;dw--;}
|
||
|
|
||
|
if(lpvPtr2)
|
||
|
{
|
||
|
lpSD=(unsigned long *)lpvPtr2;
|
||
|
dw=dwBytes2>>2;
|
||
|
while(dw) {*lpSD++=*lpSS++;dw--;}
|
||
|
}
|
||
|
|
||
|
IDirectSoundBuffer_Unlock(lpDSBSECONDARY1,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);
|
||
|
LastWrite+=lBytes;
|
||
|
if(LastWrite>=SOUNDSIZE) LastWrite-=SOUNDSIZE;
|
||
|
LastPlay=cplay;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|