mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
6372375800
commit
207e0345e0
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -324,6 +324,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
} WO;
|
||||
} static WO;
|
||||
|
||||
SndOutModule *WaveOut = &WO;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue