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

View File

@ -25,138 +25,212 @@
#define ALSA_MEM_DEF
#include "Alsa.h"
static snd_pcm_t *handle = NULL;
static snd_pcm_uframes_t buffer_size;
class AlsaMod: public SndOutModule
{
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_hw_params_t *hwparams;
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;
snd_pcm_t *handle = NULL;
snd_pcm_uframes_t buffer_size;
snd_async_handler_t *pcm_callback = NULL;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(err < 0)
uint period_time;
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));
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;
AlsaMod *data = snd_async_handler_get_callback_private( pcm_callback );
jASSUME( data != NULL );
jASSUME( data->handle == snd_async_handler_get_pcm(pcm_callback) );
// Not sure if we just need an assert, or something like this:
//if( data->handle != snd_async_handler_get_pcm(pcm_callback) ) return;
data->_InternalCallback();
}
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;
}
buffer_size=snd_pcm_status_get_avail(status);
public:
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_close(handle);
handle = NULL;
}
}
int AlsaSoundGetBytesBuffered()
{
int l;
virtual void Configure(HWND parent)
{
}
virtual bool Is51Out() const { return false; }
{
}
// failed to open?
if(handle == NULL) return SOUNDSIZE;
l = snd_pcm_avail_update(handle);
if (l<0)
return 0;
else if (l<buffer_size/2) // can we write in at least the half of fragments?
l=SOUNDSIZE; // -> no? wait
else
l=0; // -> else go on
return l;
}
s32 Test() const
{
return 0;
}
int GetEmptySampleCount() const
{
if(handle == NULL) return 0;
void AlsaSoundFeedVoiceData(unsigned char* pSound,long lBytes)
{
if (handle == NULL) return;
if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN)
snd_pcm_prepare(handle);
snd_pcm_writei(handle,pSound, lBytes/4);
}
// Returns the amount of free buffer space, in samples.
uint l = snd_pcm_avail_update(handle);
if( l < 0 ) return 0;
return (l / 1000) * (SampleRate / 1000);
}
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 );
}
} DS;
} static DS;
BOOL CALLBACK DSound::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{

View File

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

View File

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

View File

@ -957,19 +957,179 @@
RelativePath="..\DllInterface.cpp"
>
</File>
<File
RelativePath="..\common\PS2Edefs.h"
>
</File>
<File
RelativePath="..\common\PS2Etypes.h"
>
</File>
<File
RelativePath="..\SaveStateSPU.cpp"
>
</File>
</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
Name="Documents"