SPU2-X (Linux): Did some preliminary work on the Alsa driver.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@664 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-03-03 04:50:26 +00:00
parent 6372375800
commit 207e0345e0
6 changed files with 378 additions and 145 deletions

View File

@ -694,10 +694,10 @@ void PPACB() {
__forceinline void _PEXT5(int n) __forceinline void _PEXT5(int n)
{ {
cpuRegs.GPR.r[_Rd_].UL[n] = \ cpuRegs.GPR.r[_Rd_].UL[n] =
((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) |
((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) |
((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) |
((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16); ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16);
} }
@ -709,10 +709,10 @@ void PEXT5() {
__forceinline void _PPAC5(int n) __forceinline void _PPAC5(int n)
{ {
cpuRegs.GPR.r[_Rd_].UL[n] = \ cpuRegs.GPR.r[_Rd_].UL[n] =
((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) |
((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) |
((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) | \ ((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) |
((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000); ((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000);
} }

View File

@ -25,138 +25,212 @@
#define ALSA_MEM_DEF #define ALSA_MEM_DEF
#include "Alsa.h" #include "Alsa.h"
static snd_pcm_t *handle = NULL; class AlsaMod: public SndOutModule
static snd_pcm_uframes_t buffer_size; {
protected:
static const int PacketsPerBuffer = 1; // increase this if ALSA can't keep up with 512-sample packets
static const int MAX_BUFFER_COUNT = 4;
static const int NumBuffers = 4; // TODO: this should be configurable someday -- lower values reduce latency.
int AlsaSetupSound() snd_pcm_t *handle = NULL;
{ snd_pcm_uframes_t buffer_size;
snd_pcm_hw_params_t *hwparams; snd_async_handler_t *pcm_callback = NULL;
snd_pcm_sw_params_t *swparams;
snd_pcm_status_t *status;
unsigned int pspeed = SAMPLE_RATE;
int pchannels = 2;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
unsigned int buffer_time = SOUNDSIZE;
unsigned int period_time= buffer_time / 4;
int err;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); uint period_time;
if(err < 0) uint buffer_time;
protected:
// Invoked by the static ExternalCallback method below.
void _InternalCallback()
{
snd_pcm_sframes_t avail;
int err;
avail = snd_pcm_avail_update( handle );
while (avail >= period_time )
{
StereoOut16 buff[PacketsPerBuffer * SndOutPacketSize];
StereoOut16* p1 = buff;
for( int p=0; p<PacketsPerBuffer; p++, p1+=SndOutPacketSize )
SndBuffer::ReadSamples( p1 );
snd_pcm_writei( handle, buff, period_time );
avail = snd_pcm_avail_update(handle);
}
}
// Preps and invokes the _InternalCallback above. This provides a cdecl-compliant
// entry point for our C++ified object state. :)
static void ExternalCallback( snd_async_handler_t *pcm_callback )
{ {
ERROR_LOG("Audio open error: %s\n", snd_strerror(err)); AlsaMod *data = snd_async_handler_get_callback_private( pcm_callback );
return -1;
} jASSUME( data != NULL );
jASSUME( data->handle == snd_async_handler_get_pcm(pcm_callback) );
err = snd_pcm_nonblock(handle, 0);
if(err < 0) // Not sure if we just need an assert, or something like this:
{ //if( data->handle != snd_async_handler_get_pcm(pcm_callback) ) return;
ERROR_LOG("Can't set blocking mode: %s\n", snd_strerror(err));
return -1; data->_InternalCallback();
}
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);
err = snd_pcm_hw_params_any(handle, hwparams);
if (err < 0)
{
ERROR_LOG("Broken configuration for this PCM: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
{
ERROR_LOG("Access type not available: %s\n", snd_strerror(err));
return -1;
} }
err = snd_pcm_hw_params_set_format(handle, hwparams, format); public:
if (err < 0)
{
ERROR_LOG("Sample format not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_channels(handle, hwparams, pchannels);
if (err < 0)
{
ERROR_LOG("Channels count not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0);
if (err < 0)
{
ERROR_LOG("Rate not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
if(err < 0) {
ERROR_LOG("Buffer time error: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
if (err < 0)
{
ERROR_LOG("Period time error: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params(handle, hwparams);
if (err < 0)
{
ERROR_LOG("Unable to install hw params: %s\n", snd_strerror(err));
return -1;
}
snd_pcm_status_alloca(&status);
err = snd_pcm_status(handle, status);
if(err < 0)
{
ERROR_LOG("Unable to get status: %s\n", snd_strerror(err));
return -1;
}
buffer_size=snd_pcm_status_get_avail(status);
return 0; s32 Init()
} {
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
snd_pcm_status_t *status;
int pchannels = 2;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
// buffer time and period time are in microseconds...
// (don't simplify the equation below -- it'll just cause integer rounding errors.
period_time = (SndOutPacketSize*1000) / (SampleRate / 1000);
buffer_time = period_time * NumBuffers;
int err;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(err < 0)
{
ERROR_LOG("Audio open error: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_nonblock(handle, 0);
if(err < 0)
{
ERROR_LOG("Can't set blocking mode: %s\n", snd_strerror(err));
return -1;
}
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);
err = snd_pcm_hw_params_any(handle, hwparams);
if (err < 0)
{
ERROR_LOG("Broken configuration for this PCM: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0)
{
ERROR_LOG("Access type not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_format(handle, hwparams, format);
if (err < 0)
{
ERROR_LOG("Sample format not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_channels(handle, hwparams, pchannels);
if (err < 0)
{
ERROR_LOG("Channels count not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0);
if (err < 0)
{
ERROR_LOG("Rate not available: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
if(err < 0) {
ERROR_LOG("Buffer time error: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
if (err < 0)
{
ERROR_LOG("Period time error: %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params(handle, hwparams);
if (err < 0)
{
ERROR_LOG("Unable to install hw params: %s\n", snd_strerror(err));
return -1;
}
snd_pcm_status_alloca(&status);
err = snd_pcm_status(handle, status);
if(err < 0)
{
ERROR_LOG("Unable to get status: %s\n", snd_strerror(err));
return -1;
}
// Bind our asynchronous callback magic:
snd_async_add_pcm_handler( &pcm_callback, handle, ExternalCallback, this );
snd_pcm_start( handle );
// Diagnostic code:
//buffer_size = snd_pcm_status_get_avail(status);
return 0;
}
void Close()
{
if(handle == NULL) return;
void AlsaRemoveSound()
{
if(handle != NULL) {
snd_pcm_drop(handle); snd_pcm_drop(handle);
snd_pcm_close(handle); snd_pcm_close(handle);
handle = NULL; handle = NULL;
} }
}
int AlsaSoundGetBytesBuffered() virtual void Configure(HWND parent)
{ {
int l; }
virtual bool Is51Out() const { return false; }
{
}
// failed to open? s32 Test() const
if(handle == NULL) return SOUNDSIZE; {
return 0;
l = snd_pcm_avail_update(handle); }
if (l<0) int GetEmptySampleCount() const
return 0; {
else if (l<buffer_size/2) // can we write in at least the half of fragments? if(handle == NULL) return 0;
l=SOUNDSIZE; // -> no? wait
else
l=0; // -> else go on
return l;
}
void AlsaSoundFeedVoiceData(unsigned char* pSound,long lBytes) // Returns the amount of free buffer space, in samples.
{ uint l = snd_pcm_avail_update(handle);
if (handle == NULL) return; if( l < 0 ) return 0;
return (l / 1000) * (SampleRate / 1000);
if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN) }
snd_pcm_prepare(handle);
snd_pcm_writei(handle,pSound, lBytes/4); const wchar_t* GetIdent() const
} {
return L"Alsa";
}
const wchar_t* GetLongName() const
{
return L"Alsa ('tis all ya get)";
}
void ReadSettings()
{
}
void WriteSettings() const
{
}
} static Alsa;
SndOutModule *AlsaOut = &Alsa;

View File

@ -474,7 +474,7 @@ public:
CfgWriteBool( L"DSOUNDOUT", L"Use_Hardware", m_UseHardware ); CfgWriteBool( L"DSOUNDOUT", L"Use_Hardware", m_UseHardware );
} }
} DS; } static DS;
BOOL CALLBACK DSound::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) BOOL CALLBACK DSound::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{ {

View File

@ -22,7 +22,6 @@
#define _WIN32_DCOM #define _WIN32_DCOM
#include "Dialogs.h" #include "Dialogs.h"
#include <MMReg.h>
#include <xaudio2.h> #include <xaudio2.h>
@ -35,11 +34,11 @@ namespace Exception
{ {
switch( hr ) switch( hr )
{ {
case XAUDIO2_E_INVALID_CALL: case XAUDIO2_E_INVALID_CALL:
return "Invalid call for the XA2 object state."; return "Invalid call for the XA2 object state.";
case XAUDIO2_E_DEVICE_INVALIDATED: case XAUDIO2_E_DEVICE_INVALIDATED:
return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing."; return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing.";
} }
return "Unknown error code!"; return "Unknown error code!";
} }
@ -375,6 +374,6 @@ public:
{ {
} }
} XA2; } static XA2;
SndOutModule *XAudio2Out = &XA2; SndOutModule *XAudio2Out = &XA2;

View File

@ -324,6 +324,6 @@ public:
{ {
} }
} WO; } static WO;
SndOutModule *WaveOut = &WO; SndOutModule *WaveOut = &WO;

View File

@ -957,19 +957,179 @@
RelativePath="..\DllInterface.cpp" RelativePath="..\DllInterface.cpp"
> >
</File> </File>
<File
RelativePath="..\common\PS2Edefs.h"
>
</File>
<File
RelativePath="..\common\PS2Etypes.h"
>
</File>
<File <File
RelativePath="..\SaveStateSPU.cpp" RelativePath="..\SaveStateSPU.cpp"
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="Linux"
>
<File
RelativePath="..\Linux\Alsa.cpp"
>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Linux\Config.cpp"
>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Linux\Dialogs.cpp"
>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Linux\Linux.cpp"
>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<Filter
Name="Include"
>
<File
RelativePath="..\Linux\Alsa.h"
>
</File>
<File
RelativePath="..\Linux\Config.h"
>
</File>
<File
RelativePath="..\Linux\Dialogs.h"
>
</File>
<File
RelativePath="..\Linux\Linux.h"
>
</File>
</Filter>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Documents" Name="Documents"