mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X: Added audio expansion support to the portaudio backend. This change also corrects the volume in normal stereo mode.
Removed an useless method from the module interfaces. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4858 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
a22b36815c
commit
c0f9d1b619
|
@ -57,7 +57,6 @@ public:
|
|||
void Close() { }
|
||||
s32 Test() const { return 0; }
|
||||
void Configure(uptr parent) { }
|
||||
bool Is51Out() const { return false; }
|
||||
int GetEmptySampleCount() { return 0; }
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
|
@ -229,16 +228,21 @@ template<typename T> void SndBuffer::ReadSamples(T* bData)
|
|||
|
||||
template void SndBuffer::ReadSamples(StereoOut16*);
|
||||
template void SndBuffer::ReadSamples(StereoOut32*);
|
||||
|
||||
//template void SndBuffer::ReadSamples(StereoOutFloat*);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out16*);
|
||||
template void SndBuffer::ReadSamples(StereoQuadOut16*);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16DplII*);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out16*);
|
||||
//template void SndBuffer::ReadSamples(Stereo21Out32*);
|
||||
//template void SndBuffer::ReadSamples(Stereo41Out32*);
|
||||
//template void SndBuffer::ReadSamples(Stereo51Out32*);
|
||||
|
||||
template void SndBuffer::ReadSamples(Stereo20Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out32*);
|
||||
|
||||
void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ static const int SndOutPacketSize = 64;
|
|||
// downsamples 32 bit samples to 16 bit sound driver output (this way timestretching and
|
||||
// DSP effects get better precision results)
|
||||
static const int SndOutVolumeShift = 12;
|
||||
static const int SndOutVolumeShift32 = 16-SndOutVolumeShift; // shift up, not down
|
||||
|
||||
// Samplerate of the SPU2. For accurate playback we need to match this
|
||||
// exactly. Trying to scale samplerates and maintain SPU2's Ts timing accuracy
|
||||
|
@ -111,7 +112,7 @@ struct Stereo21Out16
|
|||
}
|
||||
};
|
||||
|
||||
struct StereoQuadOut16
|
||||
struct Stereo40Out16
|
||||
{
|
||||
s16 Left;
|
||||
s16 Right;
|
||||
|
@ -127,6 +128,22 @@ struct StereoQuadOut16
|
|||
}
|
||||
};
|
||||
|
||||
struct Stereo40Out32
|
||||
{
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
s32 LeftBack;
|
||||
s32 RightBack;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
LeftBack = src.Left << SndOutVolumeShift32;
|
||||
RightBack = src.Right << SndOutVolumeShift32;
|
||||
}
|
||||
};
|
||||
|
||||
struct Stereo41Out16
|
||||
{
|
||||
s16 Left;
|
||||
|
@ -314,11 +331,55 @@ struct Stereo71Out16
|
|||
}
|
||||
};
|
||||
|
||||
struct Stereo71Out32
|
||||
{
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
s32 Center;
|
||||
s32 LFE;
|
||||
s32 LeftBack;
|
||||
s32 RightBack;
|
||||
s32 LeftSide;
|
||||
s32 RightSide;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
Center = (src.Left + src.Right) << (SndOutVolumeShift32 - 1);
|
||||
LFE = Center;
|
||||
LeftBack = src.Left << SndOutVolumeShift32;
|
||||
RightBack = src.Right << SndOutVolumeShift32;
|
||||
|
||||
LeftSide = src.Left << (SndOutVolumeShift32 - 1);
|
||||
RightSide = src.Right << (SndOutVolumeShift32 - 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct Stereo20Out32
|
||||
{
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
}
|
||||
};
|
||||
|
||||
struct Stereo21Out32
|
||||
{
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
s32 LFE;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
LFE = (src.Left + src.Right) << (SndOutVolumeShift32 - 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct Stereo41Out32
|
||||
|
@ -328,6 +389,16 @@ struct Stereo41Out32
|
|||
s32 LFE;
|
||||
s32 LeftBack;
|
||||
s32 RightBack;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
LFE = (src.Left + src.Right) << (SndOutVolumeShift32 - 1);
|
||||
|
||||
LeftBack = src.Left << SndOutVolumeShift32;
|
||||
RightBack = src.Right << SndOutVolumeShift32;
|
||||
}
|
||||
};
|
||||
|
||||
struct Stereo51Out32
|
||||
|
@ -338,6 +409,16 @@ struct Stereo51Out32
|
|||
s32 LFE;
|
||||
s32 LeftBack;
|
||||
s32 RightBack;
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
Left = src.Left << SndOutVolumeShift32;
|
||||
Right = src.Right << SndOutVolumeShift32;
|
||||
Center = (src.Left + src.Right) << (SndOutVolumeShift32 - 1);
|
||||
LFE = Center;
|
||||
LeftBack = src.Left << SndOutVolumeShift32;
|
||||
RightBack = src.Right << SndOutVolumeShift32;
|
||||
}
|
||||
};
|
||||
|
||||
// Developer Note: This is a static class only (all static members).
|
||||
|
@ -430,8 +511,6 @@ public:
|
|||
// Saves settings to the INI file for this driver
|
||||
virtual void WriteSettings() const=0;
|
||||
|
||||
virtual bool Is51Out() const=0;
|
||||
|
||||
// Returns the number of empty samples in the output buffer.
|
||||
// (which is effectively the amount of data played since the last update)
|
||||
virtual int GetEmptySampleCount() =0;
|
||||
|
|
|
@ -59,33 +59,62 @@ private:
|
|||
int writtenLastTime;
|
||||
int availableLastTime;
|
||||
|
||||
int actualUsedChannels;
|
||||
|
||||
bool started;
|
||||
PaStream* stream;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Stuff necessary for speaker expansion
|
||||
class SampleReader
|
||||
{
|
||||
public:
|
||||
int ActualPaCallback( const void *inputBuffer, void *outputBuffer,
|
||||
virtual int ReadSamples( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData ) = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ConvertedSampleReader : public SampleReader
|
||||
{
|
||||
int* written;
|
||||
public:
|
||||
ConvertedSampleReader(int* pWritten)
|
||||
{
|
||||
written = pWritten;
|
||||
}
|
||||
|
||||
virtual int ReadSamples( const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
StereoOut32* p1 = (StereoOut32*)outputBuffer;
|
||||
T* p1 = (T*)outputBuffer;
|
||||
|
||||
int packets = framesPerBuffer / SndOutPacketSize;
|
||||
|
||||
for(int p=0; p<packets; p++, p1+=SndOutPacketSize )
|
||||
SndBuffer::ReadSamples( p1 );
|
||||
|
||||
writtenSoFar += packets * SndOutPacketSize;
|
||||
(*written) += packets * SndOutPacketSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
SampleReader* ActualPaCallback;
|
||||
|
||||
Portaudio()
|
||||
{
|
||||
m_ApiId=-1;
|
||||
m_SuggestedLatencyMinimal = true;
|
||||
m_SuggestedLatencyMS = 20;
|
||||
|
||||
actualUsedChannels = 0;
|
||||
}
|
||||
|
||||
s32 Init()
|
||||
|
@ -148,6 +177,57 @@ public:
|
|||
{
|
||||
void* infoPtr = NULL;
|
||||
|
||||
const PaDeviceInfo * devinfo = Pa_GetDeviceInfo(deviceIndex);
|
||||
const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(devinfo->hostApi);
|
||||
|
||||
int speakers;
|
||||
switch(numSpeakers) // speakers = (numSpeakers + 1) *2; ?
|
||||
{
|
||||
case 0: speakers = 2; break; // Stereo
|
||||
case 1: speakers = 4; break; // Quadrafonic
|
||||
case 2: speakers = 6; break; // Surround 5.1
|
||||
case 3: speakers = 8; break; // Surround 7.1
|
||||
default: speakers = 2;
|
||||
}
|
||||
actualUsedChannels = devinfo->maxOutputChannels;
|
||||
if(actualUsedChannels > speakers)
|
||||
actualUsedChannels = speakers;
|
||||
|
||||
switch( actualUsedChannels )
|
||||
{
|
||||
case 2:
|
||||
ConLog( "* SPU2 > Using normal 2 speaker stereo output.\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo20Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ConLog( "* SPU2 > 2.1 speaker expansion enabled.\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo21Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ConLog( "* SPU2 > 4 speaker expansion enabled [quadraphenia]\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo40Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ConLog( "* SPU2 > 4.1 speaker expansion enabled.\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo41Out32>(&writtenSoFar);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
ConLog( "* SPU2 > 5.1 speaker expansion enabled.\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32>(&writtenSoFar); //"normal" stereo upmix
|
||||
//ActualPaCallback = new ConvertedSampleReader<Stereo51Out32DplII>(&writtenSoFar); //gigas PLII
|
||||
break;
|
||||
|
||||
default: // anything 8 or more gets the 7.1 treatment!
|
||||
ConLog( "* SPU2 > 7.1 speaker expansion enabled.\n" );
|
||||
ActualPaCallback = new ConvertedSampleReader<Stereo71Out32>(&writtenSoFar);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __WIN32__
|
||||
PaWasapiStreamInfo info = {
|
||||
sizeof(PaWasapiStreamInfo),
|
||||
|
@ -171,7 +251,7 @@ public:
|
|||
// PaTime suggestedLatency;
|
||||
// void *hostApiSpecificStreamInfo;
|
||||
deviceIndex,
|
||||
2,
|
||||
actualUsedChannels,
|
||||
paInt32,
|
||||
m_SuggestedLatencyMinimal?(SndOutPacketSize/(float)SampleRate):(m_SuggestedLatencyMS/1000.0f),
|
||||
infoPtr
|
||||
|
@ -188,7 +268,7 @@ public:
|
|||
else
|
||||
{
|
||||
err = Pa_OpenDefaultStream( &stream,
|
||||
0, 2, paInt32, 48000,
|
||||
0, actualUsedChannels, paInt32, 48000,
|
||||
SndOutPacketSize,
|
||||
PaCallback,
|
||||
NULL );
|
||||
|
@ -456,8 +536,6 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
|
@ -564,7 +642,7 @@ int PaCallback( const void *inputBuffer, void *outputBuffer,
|
|||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
{
|
||||
return PA.ActualPaCallback(inputBuffer,outputBuffer,framesPerBuffer,timeInfo,statusFlags,userData);
|
||||
return PA.ActualPaCallback->ReadSamples(inputBuffer,outputBuffer,framesPerBuffer,timeInfo,statusFlags,userData);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
@ -422,8 +422,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -306,7 +306,7 @@ public:
|
|||
|
||||
case 4:
|
||||
ConLog( "* SPU2 > 4 speaker expansion enabled [quadraphenia]\n" );
|
||||
voiceContext = new StreamingVoice<StereoQuadOut16>( pXAudio2 );
|
||||
voiceContext = new StreamingVoice<Stereo40Out16>( pXAudio2 );
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
@ -368,8 +368,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -281,8 +281,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
if (waveOutGetNumDevs() == 0) {
|
||||
|
|
Loading…
Reference in New Issue